about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/bin/rustc.rs6
-rw-r--r--src/bootstrap/bin/rustdoc.rs2
-rw-r--r--src/bootstrap/builder.rs24
-rw-r--r--src/bootstrap/builder/tests.rs1
-rw-r--r--src/bootstrap/compile.rs20
-rw-r--r--src/bootstrap/config.rs7
-rw-r--r--src/bootstrap/dist.rs4
-rw-r--r--src/bootstrap/doc.rs2
-rw-r--r--src/bootstrap/flags.rs2
-rw-r--r--src/bootstrap/install.rs5
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/metadata.rs1
-rw-r--r--src/bootstrap/native.rs4
-rw-r--r--src/bootstrap/test.rs9
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/bootstrap/toolstate.rs2
-rw-r--r--src/bootstrap/util.rs2
-rw-r--r--src/doc/rustdoc/src/the-doc-attribute.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md12
-rw-r--r--src/libcore/intrinsics.rs5
-rw-r--r--src/libcore/iter/sources.rs2
-rw-r--r--src/libcore/lib.rs5
-rw-r--r--src/libcore/num/mod.rs147
-rw-r--r--src/librustc/arena.rs1
-rw-r--r--src/librustc/ich/impls_hir.rs28
-rw-r--r--src/librustc/infer/canonical/mod.rs339
-rw-r--r--src/librustc/infer/mod.rs11
-rw-r--r--src/librustc/infer/region_constraints/mod.rs26
-rw-r--r--src/librustc/infer/type_variable.rs15
-rw-r--r--src/librustc/infer/types/canonical.rs357
-rw-r--r--src/librustc/infer/types/mod.rs31
-rw-r--r--src/librustc/infer/unify_key.rs15
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/query/mod.rs5
-rw-r--r--src/librustc/traits/auto_trait.rs1
-rw-r--r--src/librustc/traits/error_reporting/suggestions.rs4
-rw-r--r--src/librustc/traits/mod.rs691
-rw-r--r--src/librustc/traits/project.rs43
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs79
-rw-r--r--src/librustc/traits/query/method_autoderef.rs34
-rw-r--r--src/librustc/traits/query/mod.rs37
-rw-r--r--src/librustc/traits/query/normalize.rs9
-rw-r--r--src/librustc/traits/query/outlives_bounds.rs38
-rw-r--r--src/librustc/traits/query/type_op/ascribe_user_type.rs17
-rw-r--r--src/librustc/traits/query/type_op/eq.rs14
-rw-r--r--src/librustc/traits/query/type_op/mod.rs2
-rw-r--r--src/librustc/traits/query/type_op/normalize.rs14
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs11
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs14
-rw-r--r--src/librustc/traits/select.rs302
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs200
-rw-r--r--src/librustc/traits/structural_impls.rs705
-rw-r--r--src/librustc/traits/types/mod.rs736
-rw-r--r--src/librustc/traits/types/query.rs332
-rw-r--r--src/librustc/traits/types/select.rs290
-rw-r--r--src/librustc/traits/types/specialization_graph.rs199
-rw-r--r--src/librustc/traits/types/structural_impls.rs712
-rw-r--r--src/librustc/ty/error.rs10
-rw-r--r--src/librustc/ty/mod.rs48
-rw-r--r--src/librustc_ast_lowering/item.rs48
-rw-r--r--src/librustc_ast_lowering/lib.rs28
-rw-r--r--src/librustc_ast_passes/ast_validation.rs336
-rw-r--r--src/librustc_ast_passes/feature_gate.rs69
-rw-r--r--src/librustc_ast_passes/node_count.rs8
-rw-r--r--src/librustc_ast_pretty/pprust.rs64
-rw-r--r--src/librustc_builtin_macros/global_allocator.rs2
-rw-r--r--src/librustc_builtin_macros/log_syntax.rs1
-rw-r--r--src/librustc_builtin_macros/test_harness.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs78
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs10
-rw-r--r--src/librustc_error_codes/error_codes/E0264.md4
-rw-r--r--src/librustc_error_codes/error_codes/E0267.md6
-rw-r--r--src/librustc_error_codes/error_codes/E0268.md7
-rw-r--r--src/librustc_error_codes/error_codes/E0454.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0458.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0459.md2
-rw-r--r--src/librustc_expand/base.rs6
-rw-r--r--src/librustc_expand/expand.rs54
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_feature/removed.rs4
-rw-r--r--src/librustc_hir/hir.rs4
-rw-r--r--src/librustc_hir/stable_hash_impls.rs17
-rw-r--r--src/librustc_incremental/persist/file_format.rs3
-rw-r--r--src/librustc_interface/callbacks.rs1
-rw-r--r--src/librustc_interface/passes.rs4
-rw-r--r--src/librustc_lint/builtin.rs46
-rw-r--r--src/librustc_lint/early.rs39
-rw-r--r--src/librustc_lint/passes.rs3
-rw-r--r--src/librustc_lint/unused.rs8
-rw-r--r--src/librustc_macros/src/lift.rs2
-rw-r--r--src/librustc_macros/src/query.rs1
-rw-r--r--src/librustc_macros/src/symbols.rs1
-rw-r--r--src/librustc_macros/src/type_foldable.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs27
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs19
-rw-r--r--src/librustc_parse/parser/diagnostics.rs50
-rw-r--r--src/librustc_parse/parser/expr.rs3
-rw-r--r--src/librustc_parse/parser/item.rs122
-rw-r--r--src/librustc_parse/parser/path.rs3
-rw-r--r--src/librustc_parse/parser/stmt.rs2
-rw-r--r--src/librustc_parse/parser/ty.rs61
-rw-r--r--src/librustc_passes/dead.rs1
-rw-r--r--src/librustc_passes/hir_stats.rs25
-rw-r--r--src/librustc_passes/liveness.rs14
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs21
-rw-r--r--src/librustc_resolve/def_collector.rs39
-rw-r--r--src/librustc_resolve/diagnostics.rs293
-rw-r--r--src/librustc_resolve/late.rs54
-rw-r--r--src/librustc_resolve/lifetimes.rs87
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs9
-rw-r--r--src/librustc_save_analysis/lib.rs4
-rw-r--r--src/librustc_save_analysis/sig.rs3
-rw-r--r--src/librustc_session/config.rs4
-rw-r--r--src/librustc_session/options.rs2
-rw-r--r--src/librustc_session/session.rs6
-rw-r--r--src/librustc_span/symbol.rs5
-rw-r--r--src/librustc_ty/ty.rs9
-rw-r--r--src/librustc_typeck/astconv.rs11
-rw-r--r--src/librustc_typeck/check/autoderef.rs4
-rw-r--r--src/librustc_typeck/variance/mod.rs1
-rw-r--r--src/librustdoc/clean/utils.rs1
-rw-r--r--src/librustdoc/config.rs2
-rw-r--r--src/librustdoc/core.rs1
-rw-r--r--src/librustdoc/html/render.rs11
-rw-r--r--src/librustdoc/markdown.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs1
-rw-r--r--src/librustdoc/test.rs3
-rw-r--r--src/libstd/io/buffered.rs4
-rw-r--r--src/libstd/lib.rs6
-rw-r--r--src/libstd/sys/unix/time.rs1
-rw-r--r--src/libstd/tests/run-time-detect.rs1
-rw-r--r--src/libsyntax/ast.rs15
-rw-r--r--src/libsyntax/mut_visit.rs7
-rw-r--r--src/libsyntax/visit.rs136
-rw-r--r--src/libtest/cli.rs1
-rw-r--r--src/libtest/console.rs2
m---------src/stdarch0
-rw-r--r--src/test/ui/async-await/issues/issue-63388-2.nll.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-63388-2.stderr2
-rw-r--r--src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs7
-rw-r--r--src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr14
-rw-r--r--src/test/ui/coherence/coherence-impls-send.rs4
-rw-r--r--src/test/ui/coherence/coherence-impls-send.stderr23
-rw-r--r--src/test/ui/consts/const-int-arithmetic.rs130
-rw-r--r--src/test/ui/did_you_mean/recursion_limit.stderr2
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.stderr2
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_macro.stderr2
-rw-r--r--src/test/ui/error-codes/E0055.stderr2
-rw-r--r--src/test/ui/error-codes/E0106.stderr16
-rw-r--r--src/test/ui/error-codes/E0275.stderr2
-rw-r--r--src/test/ui/extern/extern-ffi-fn-with-body.rs2
-rw-r--r--src/test/ui/extern/extern-ffi-fn-with-body.stderr10
-rw-r--r--src/test/ui/generic/generic-extern-lifetime.stderr12
-rw-r--r--src/test/ui/impl-header-lifetime-elision/assoc-type.stderr8
-rw-r--r--src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr4
-rw-r--r--src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr10
-rw-r--r--src/test/ui/infinite/infinite-autoderef.stderr6
-rw-r--r--src/test/ui/infinite/infinite-macro-expansion.stderr2
-rw-r--r--src/test/ui/issues/issue-16098.stderr2
-rw-r--r--src/test/ui/issues/issue-18400.stderr2
-rw-r--r--src/test/ui/issues/issue-19707.stderr22
-rw-r--r--src/test/ui/issues/issue-20413.stderr4
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr4
-rw-r--r--src/test/ui/issues/issue-26638.stderr6
-rw-r--r--src/test/ui/issues/issue-30255.stderr18
-rw-r--r--src/test/ui/issues/issue-38940.stderr2
-rw-r--r--src/test/ui/issues/issue-39616.rs3
-rw-r--r--src/test/ui/issues/issue-39616.stderr4
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr12
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr6
-rw-r--r--src/test/ui/lint/lint-unnecessary-parens.rs3
-rw-r--r--src/test/ui/lint/lint-unnecessary-parens.stderr36
-rw-r--r--src/test/ui/macros/issue-54441.stderr4
-rw-r--r--src/test/ui/macros/trace_faulty_macros.stderr2
-rw-r--r--src/test/ui/no-patterns-in-args-2.rs4
-rw-r--r--src/test/ui/no-patterns-in-args-2.stderr6
-rw-r--r--src/test/ui/no-patterns-in-args-macro.rs6
-rw-r--r--src/test/ui/no-patterns-in-args-macro.stderr4
-rw-r--r--src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs14
-rw-r--r--src/test/ui/overlap-doesnt-conflict-with-specialization.rs3
-rw-r--r--src/test/ui/overlap-marker-trait.rs31
-rw-r--r--src/test/ui/overlap-marker-trait.stderr12
-rw-r--r--src/test/ui/parser/duplicate-visibility.rs2
-rw-r--r--src/test/ui/parser/duplicate-visibility.stderr4
-rw-r--r--src/test/ui/parser/fn-body-optional-semantic-fail.rs27
-rw-r--r--src/test/ui/parser/fn-body-optional-semantic-fail.stderr40
-rw-r--r--src/test/ui/parser/fn-body-optional-syntactic-pass.rs31
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.rs57
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr136
-rw-r--r--src/test/ui/parser/fn-header-syntactic-pass.rs55
-rw-r--r--src/test/ui/parser/issue-24780.rs2
-rw-r--r--src/test/ui/parser/issue-24780.stderr4
-rw-r--r--src/test/ui/parser/issue-63135.rs2
-rw-r--r--src/test/ui/parser/issue-63135.stderr8
-rw-r--r--src/test/ui/parser/issue-68788-in-trait-item-propagation.rs21
-rw-r--r--src/test/ui/parser/missing_right_paren.rs2
-rw-r--r--src/test/ui/parser/missing_right_paren.stderr8
-rw-r--r--src/test/ui/parser/no-const-fn-in-extern-block.rs4
-rw-r--r--src/test/ui/parser/no-const-fn-in-extern-block.stderr21
-rw-r--r--src/test/ui/parser/not-a-pred.stderr4
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-59191.rs16
-rw-r--r--src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs8
-rw-r--r--src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr17
-rw-r--r--src/test/ui/proc-macro/item-error.stderr4
-rw-r--r--src/test/ui/regions/regions-in-enums-anon.stderr4
-rw-r--r--src/test/ui/regions/regions-in-structs-anon.stderr4
-rw-r--r--src/test/ui/regions/regions-name-undeclared.stderr20
-rw-r--r--src/test/ui/rfc1623-2.rs13
-rw-r--r--src/test/ui/rfc1623-2.stderr29
-rw-r--r--src/test/ui/rfc1623.rs13
-rw-r--r--src/test/ui/rfc1623.stderr51
-rw-r--r--src/test/ui/suggestions/fn-missing-lifetime-in-item.rs8
-rw-r--r--src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr49
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime.rs2
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime.stderr14
-rw-r--r--src/test/ui/suggestions/return-without-lifetime.stderr4
-rw-r--r--src/test/ui/suggestions/suggest-split-at-mut.rs8
-rw-r--r--src/test/ui/suggestions/suggest-split-at-mut.stderr15
-rw-r--r--src/test/ui/super-fast-paren-parsing.rs1
-rw-r--r--src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs (renamed from src/test/ui/traits/overlap-permitted-for-marker-traits-neg.rs)5
-rw-r--r--src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr11
-rw-r--r--src/test/ui/traits/overlap-permitted-for-marker-traits.rs27
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr4
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr4
-rw-r--r--src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr6
-rw-r--r--src/test/ui/underscore-lifetime/in-struct.stderr8
-rw-r--r--src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr6
227 files changed, 5029 insertions, 3803 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index a34ec44566b..a8c00c8c3ca 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -47,7 +47,7 @@ fn main() {
     };
     let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
     let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
-    let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));
+    let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);
 
     let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
     let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
@@ -64,7 +64,7 @@ fn main() {
     if let Some(crate_name) = crate_name {
         if let Some(target) = env::var_os("RUSTC_TIME") {
             if target == "all"
-                || target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
+                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
             {
                 cmd.arg("-Ztime");
             }
@@ -189,7 +189,7 @@ fn main() {
                 crate_name,
                 is_test,
                 dur.as_secs(),
-                dur.subsec_nanos() / 1_000_000
+                dur.subsec_millis()
             );
 
             match status.code() {
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 8c8b33a4e4e..04345867bf5 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -61,7 +61,7 @@ fn main() {
     }
 
     // Needed to be able to run all rustdoc tests.
-    if let Some(_) = env::var_os("RUSTDOC_GENERATE_REDIRECT_PAGES") {
+    if env::var_os("RUSTDOC_GENERATE_REDIRECT_PAGES").is_some() {
         // This "unstable-options" can be removed when `--generate-redirect-pages` is stabilized
         if !has_unstable {
             cmd.arg("-Z").arg("unstable-options");
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index d9c894aa9c6..18f6fda7608 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -510,7 +510,7 @@ impl<'a> Builder<'a> {
             Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
-        let builder = Builder {
+        Builder {
             build,
             top_stage: build.config.stage.unwrap_or(2),
             kind,
@@ -518,9 +518,7 @@ impl<'a> Builder<'a> {
             stack: RefCell::new(Vec::new()),
             time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
             paths: paths.to_owned(),
-        };
-
-        builder
+        }
     }
 
     pub fn execute_cli(&self) {
@@ -753,13 +751,12 @@ impl<'a> Builder<'a> {
             cargo.env("RUST_CHECK", "1");
         }
 
-        let stage;
-        if compiler.stage == 0 && self.local_rebuild {
+        let stage = if compiler.stage == 0 && self.local_rebuild {
             // Assume the local-rebuild rustc already has stage1 features.
-            stage = 1;
+            1
         } else {
-            stage = compiler.stage;
-        }
+            compiler.stage
+        };
 
         let mut rustflags = Rustflags::new(&target);
         if stage != 0 {
@@ -1252,12 +1249,7 @@ impl<'a> Builder<'a> {
         };
 
         if self.config.print_step_timings && dur > Duration::from_millis(100) {
-            println!(
-                "[TIMING] {:?} -- {}.{:03}",
-                step,
-                dur.as_secs(),
-                dur.subsec_nanos() / 1_000_000
-            );
+            println!("[TIMING] {:?} -- {}.{:03}", step, dur.as_secs(), dur.subsec_millis());
         }
 
         {
@@ -1302,7 +1294,7 @@ impl Rustflags {
 
     fn arg(&mut self, arg: &str) -> &mut Self {
         assert_eq!(arg.split_whitespace().count(), 1);
-        if self.0.len() > 0 {
+        if !self.0.is_empty() {
             self.0.push_str(" ");
         }
         self.0.push_str(arg);
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 5fefb972866..cca8ab80c93 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -19,7 +19,6 @@ fn configure(host: &[&str], target: &[&str]) -> Config {
     config.out = dir;
     config.build = INTERNER.intern_str("A");
     config.hosts = vec![config.build]
-        .clone()
         .into_iter()
         .chain(host.iter().map(|s| INTERNER.intern_str(s)))
         .collect::<Vec<_>>();
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index eced03506ab..7dded96e18e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -18,7 +18,6 @@ use std::str;
 use build_helper::{output, t, up_to_date};
 use filetime::FileTime;
 use serde::Deserialize;
-use serde_json;
 
 use crate::builder::Cargo;
 use crate::dist;
@@ -149,7 +148,8 @@ fn copy_third_party_objects(
     // which is provided by std for this target.
     if target == "x86_64-fortanix-unknown-sgx" {
         let src_path_env = "X86_FORTANIX_SGX_LIBS";
-        let src = env::var(src_path_env).expect(&format!("{} not found in env", src_path_env));
+        let src =
+            env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
         copy_and_stamp(Path::new(&src), "libunwind.a");
     }
 
@@ -361,7 +361,7 @@ impl Step for StartupObjects {
                 );
             }
 
-            let target = sysroot_dir.join(file.to_string() + ".o");
+            let target = sysroot_dir.join((*file).to_string() + ".o");
             builder.copy(dst_file, &target);
             target_deps.push(target);
         }
@@ -515,7 +515,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interne
         .env("CFG_VERSION", builder.rust_version())
         .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
 
-    let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib"));
+    let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
 
     if let Some(ref ver_date) = builder.rust_info.commit_date() {
@@ -843,11 +843,11 @@ pub fn run_cargo(
         };
         for filename in filenames {
             // Skip files like executables
-            if !filename.ends_with(".rlib")
-                && !filename.ends_with(".lib")
-                && !filename.ends_with(".a")
-                && !is_dylib(&filename)
-                && !(is_check && filename.ends_with(".rmeta"))
+            if !(filename.ends_with(".rlib")
+                || filename.ends_with(".lib")
+                || filename.ends_with(".a")
+                || is_dylib(&filename)
+                || (is_check && filename.ends_with(".rmeta")))
             {
                 continue;
             }
@@ -905,7 +905,7 @@ pub fn run_cargo(
     for (prefix, extension, expected_len) in toplevel {
         let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
             filename.starts_with(&prefix[..])
-                && filename[prefix.len()..].starts_with("-")
+                && filename[prefix.len()..].starts_with('-')
                 && filename.ends_with(&extension[..])
                 && meta.len() == expected_len
         });
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 110c8b844d5..709cf2908ea 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -16,7 +16,6 @@ use crate::flags::Flags;
 pub use crate::flags::Subcommand;
 use build_helper::t;
 use serde::Deserialize;
-use toml;
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
@@ -440,7 +439,7 @@ impl Config {
                     }
                 }
             })
-            .unwrap_or_else(|| TomlConfig::default());
+            .unwrap_or_else(TomlConfig::default);
 
         let build = toml.build.clone().unwrap_or_default();
         // set by bootstrap.py
@@ -539,7 +538,7 @@ impl Config {
             config.llvm_ldflags = llvm.ldflags.clone();
             set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
             config.llvm_use_linker = llvm.use_linker.clone();
-            config.llvm_allow_old_toolchain = llvm.allow_old_toolchain.clone();
+            config.llvm_allow_old_toolchain = llvm.allow_old_toolchain;
         }
 
         if let Some(ref rust) = toml.rust {
@@ -606,7 +605,7 @@ impl Config {
                 target.ar = cfg.ar.clone().map(PathBuf::from);
                 target.ranlib = cfg.ranlib.clone().map(PathBuf::from);
                 target.linker = cfg.linker.clone().map(PathBuf::from);
-                target.crt_static = cfg.crt_static.clone();
+                target.crt_static = cfg.crt_static;
                 target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
                 target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from);
                 target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index facf816857f..8003d8906e8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -828,7 +828,7 @@ impl Step for Analysis {
         assert!(builder.config.extended);
         let name = pkgname(builder, "rust-analysis");
 
-        if &compiler.host != builder.config.build {
+        if compiler.host != builder.config.build {
             return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
         }
 
@@ -877,7 +877,7 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str]
             Some(path) => path,
             None => return false,
         };
-        if spath.ends_with("~") || spath.ends_with(".pyc") {
+        if spath.ends_with('~') || spath.ends_with(".pyc") {
             return false;
         }
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 204056598d9..b0d9a5b9464 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -560,7 +560,7 @@ impl Step for Rustdoc {
         builder.ensure(Rustc { stage, target });
 
         // Build rustdoc.
-        builder.ensure(tool::Rustdoc { compiler: compiler });
+        builder.ensure(tool::Rustdoc { compiler });
 
         // Symlink compiler docs to the output directory of rustdoc documentation.
         let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc");
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 2101ef27f9d..516be6a30c2 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -571,7 +571,7 @@ fn split(s: &[String]) -> Vec<String> {
 }
 
 fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
-    match matches.opt_str("warnings").as_ref().map(|v| v.as_str()) {
+    match matches.opt_str("warnings").as_deref() {
         Some("deny") => Some(true),
         Some("warn") => Some(false),
         Some(value) => {
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index f8734ebdf42..6549262811b 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -126,9 +126,8 @@ fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
         None => return path.to_path_buf(),
     };
     for part in path.components() {
-        match part {
-            Component::Normal(s) => ret.push(s),
-            _ => {}
+        if let Component::Normal(s) = part {
+            ret.push(s)
         }
     }
     ret
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 637323331f5..0db4fb38901 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -444,7 +444,7 @@ impl Build {
             builder.execute_cli();
         } else {
             let builder = builder::Builder::new(&self);
-            let _ = builder.execute_cli();
+            builder.execute_cli();
         }
 
         // Check for postponed failures from `test --no-fail-fast`.
@@ -839,7 +839,7 @@ impl Build {
             .target_config
             .get(&target)
             .and_then(|t| t.musl_root.as_ref())
-            .or(self.config.musl_root.as_ref())
+            .or_else(|| self.config.musl_root.as_ref())
             .map(|p| &**p)
     }
 
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index 8a26adc7ed5..292aa3b1e24 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -5,7 +5,6 @@ use std::process::Command;
 
 use build_helper::output;
 use serde::Deserialize;
-use serde_json;
 
 use crate::cache::INTERNER;
 use crate::{Build, Crate};
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 5bbd9f47fc9..1cfb4b2f63b 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -15,8 +15,6 @@ use std::path::{Path, PathBuf};
 use std::process::Command;
 
 use build_helper::{output, t};
-use cc;
-use cmake;
 
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
@@ -205,7 +203,7 @@ impl Step for Llvm {
             cfg.define("LLVM_ENABLE_LIBXML2", "OFF");
         }
 
-        if enabled_llvm_projects.len() > 0 {
+        if !enabled_llvm_projects.is_empty() {
             enabled_llvm_projects.sort();
             enabled_llvm_projects.dedup();
             cfg.define("LLVM_ENABLE_PROJECTS", enabled_llvm_projects.join(";"));
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 6adf9ddaf34..8d9e6201001 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1424,13 +1424,10 @@ impl Step for ErrorIndex {
 }
 
 fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
-    match fs::read_to_string(markdown) {
-        Ok(contents) => {
-            if !contents.contains("```") {
-                return true;
-            }
+    if let Ok(contents) = fs::read_to_string(markdown) {
+        if !contents.contains("```") {
+            return true;
         }
-        Err(_) => {}
     }
 
     builder.info(&format!("doc tests for: {}", markdown.display()));
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 7f24768a4f1..67e0ed5c580 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -234,7 +234,7 @@ pub fn prepare_tool_cargo(
         cargo.env("RUSTC_EXTERNAL_TOOL", "1");
     }
 
-    let mut features = extra_features.iter().cloned().collect::<Vec<_>>();
+    let mut features = extra_features.to_vec();
     if builder.build.config.cargo_native_static {
         if path.ends_with("cargo")
             || path.ends_with("rls")
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index b068c8200ac..bb012a38855 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -124,7 +124,7 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
     let output = t!(String::from_utf8(output.stdout));
 
     for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
-        let changed = output.lines().any(|l| l.starts_with("M") && l.ends_with(submodule));
+        let changed = output.lines().any(|l| l.starts_with('M') && l.ends_with(submodule));
         eprintln!("Verifying status of {}...", tool);
         if !changed {
             continue;
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 7d1efe4610f..eac790fe504 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -98,7 +98,7 @@ impl Drop for TimeIt {
     fn drop(&mut self) {
         let time = self.1.elapsed();
         if !self.0 {
-            println!("\tfinished in {}.{:03}", time.as_secs(), time.subsec_nanos() / 1_000_000);
+            println!("\tfinished in {}.{:03}", time.as_secs(), time.subsec_millis());
         }
     }
 }
diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md
index 80ac405eb2f..ef143c8727e 100644
--- a/src/doc/rustdoc/src/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/the-doc-attribute.md
@@ -39,7 +39,7 @@ crate level, and ones that are useful at the item level.
 
 ## At the crate level
 
-These options control how the docs look at a macro level.
+These options control how the docs look at a crate level.
 
 ### `html_favicon_url`
 
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 64bff2a6fe0..414ac7e63a3 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -170,7 +170,7 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
 ## MemorySanitizer
 
 Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument
-standard library, and passing `-msan-track-origins=2` to the LLVM to track
+the standard library, and passing `-Zsanitizer-track-origins` to track the
 origins of uninitialized memory:
 
 ```shell
@@ -185,7 +185,15 @@ fn main() {
     }
 }
 
-$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
+$ export \
+  CC=clang \
+  CXX=clang++ \
+  CFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \
+  CXXFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \
+  RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
+  RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
+$ cargo clean
+$ cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
 ==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
     #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
 ...
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 416c73f50bd..2cee23a5c75 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1305,9 +1305,11 @@ extern "rust-intrinsic" {
 
     /// Performs an unchecked division, resulting in undefined behavior
     /// where y = 0 or x = `T::min_value()` and y = -1
+    #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
     /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
+    #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_rem<T>(x: T, y: T) -> T;
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
@@ -1321,14 +1323,17 @@ extern "rust-intrinsic" {
 
     /// Returns the result of an unchecked addition, resulting in
     /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+    #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_add<T>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked subtraction, resulting in
     /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+    #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_sub<T>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked multiplication, resulting in
     /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+    #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_mul<T>(x: T, y: T) -> T;
 
     /// Performs rotate left.
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index 5a31acab273..a1d4e1b31e9 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -398,7 +398,7 @@ pub fn once<T>(value: T) -> Once<T> {
 /// See its documentation for more.
 ///
 /// [`once_with`]: fn.once_with.html
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
 #[stable(feature = "iter_once_with", since = "1.43.0")]
 pub struct OnceWith<F> {
     gen: Option<F>,
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 6edf253d4bb..1fd70e1a1b0 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -72,6 +72,11 @@
 #![feature(concat_idents)]
 #![feature(const_alloc_layout)]
 #![feature(const_if_match)]
+#![feature(const_checked_int_methods)]
+#![feature(const_euclidean_int_methods)]
+#![feature(const_overflowing_int_methods)]
+#![feature(const_saturating_int_methods)]
+#![feature(const_int_unchecked_arith)]
 #![feature(const_panic)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 39c7d6d24ed..ed37b48b3e8 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -701,10 +701,11 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_add(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_add(rhs);
                 if b {None} else {Some(a)}
             }
@@ -725,10 +726,11 @@ assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_sub(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_sub(rhs);
                 if b {None} else {Some(a)}
             }
@@ -749,10 +751,11 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_mul(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_mul(rhs);
                 if b {None} else {Some(a)}
             }
@@ -774,10 +777,11 @@ assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_div(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 || (self == Self::min_value() && rhs == -1) {
                     None
                 } else {
@@ -802,10 +806,11 @@ assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None);
 assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 || (self == Self::min_value() && rhs == -1) {
                     None
                 } else {
@@ -831,10 +836,11 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_rem(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 || (self == Self::min_value() && rhs == -1) {
                     None
                 } else {
@@ -860,10 +866,11 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
 assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 || (self == Self::min_value() && rhs == -1) {
                     None
                 } else {
@@ -887,8 +894,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[inline]
-            pub fn checked_neg(self) -> Option<Self> {
+            pub const fn checked_neg(self) -> Option<Self> {
                 let (a, b) = self.overflowing_neg();
                 if b {None} else {Some(a)}
             }
@@ -908,10 +916,11 @@ assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_shl(self, rhs: u32) -> Option<Self> {
+            pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
                 let (a, b) = self.overflowing_shl(rhs);
                 if b {None} else {Some(a)}
             }
@@ -931,10 +940,11 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_shr(self, rhs: u32) -> Option<Self> {
+            pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
                 let (a, b) = self.overflowing_shr(rhs);
                 if b {None} else {Some(a)}
             }
@@ -956,8 +966,9 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);",
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[inline]
-            pub fn checked_abs(self) -> Option<Self> {
+            pub const fn checked_abs(self) -> Option<Self> {
                 if self.is_negative() {
                     self.checked_neg()
                 } else {
@@ -1080,8 +1091,9 @@ $EndFeature, "
 ```"),
 
             #[unstable(feature = "saturating_neg", issue = "59983")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")]
             #[inline]
-            pub fn saturating_neg(self) -> Self {
+            pub const fn saturating_neg(self) -> Self {
                 intrinsics::saturating_sub(0, self)
             }
         }
@@ -1106,8 +1118,9 @@ $EndFeature, "
 ```"),
 
             #[unstable(feature = "saturating_neg", issue = "59983")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")]
             #[inline]
-            pub fn saturating_abs(self) -> Self {
+            pub const fn saturating_abs(self) -> Self {
                 if self.is_negative() {
                     self.saturating_neg()
                 } else {
@@ -1133,17 +1146,19 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($Self
 $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn saturating_mul(self, rhs: Self) -> Self {
-                self.checked_mul(rhs).unwrap_or_else(|| {
-                    if (self < 0) == (rhs < 0) {
+            pub const fn saturating_mul(self, rhs: Self) -> Self {
+                match self.checked_mul(rhs) {
+                    Some(x) => x,
+                    None => if (self < 0) == (rhs < 0) {
                         Self::max_value()
                     } else {
                         Self::min_value()
                     }
-                })
+                }
             }
         }
 
@@ -1269,10 +1284,11 @@ assert_eq!((-128i8).wrapping_div(-1), -128);",
 $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_div(self, rhs: Self) -> Self {
+            pub const fn wrapping_div(self, rhs: Self) -> Self {
                 self.overflowing_div(rhs).0
             }
         }
@@ -1298,10 +1314,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
 assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
+            pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
                 self.overflowing_div_euclid(rhs).0
             }
         }
@@ -1328,10 +1345,11 @@ assert_eq!((-128i8).wrapping_rem(-1), 0);",
 $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_rem(self, rhs: Self) -> Self {
+            pub const fn wrapping_rem(self, rhs: Self) -> Self {
                 self.overflowing_rem(rhs).0
             }
         }
@@ -1356,10 +1374,11 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
 assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
+            pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
                 self.overflowing_rem_euclid(rhs).0
             }
         }
@@ -1635,9 +1654,10 @@ $EndFeature, "
 ```"),
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
                 if self == Self::min_value() && rhs == -1 {
                     (self, true)
                 } else {
@@ -1669,9 +1689,10 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi
 ```"),
             #[inline]
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
                 if self == Self::min_value() && rhs == -1 {
                     (self, true)
                 } else {
@@ -1703,9 +1724,10 @@ $EndFeature, "
 ```"),
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
                 if self == Self::min_value() && rhs == -1 {
                     (0, true)
                 } else {
@@ -1736,10 +1758,11 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
 assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
                 if self == Self::min_value() && rhs == -1 {
                     (0, true)
                 } else {
@@ -1981,11 +2004,12 @@ assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
 assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn div_euclid(self, rhs: Self) -> Self {
+            pub const fn div_euclid(self, rhs: Self) -> Self {
                 let q = self / rhs;
                 if self % rhs < 0 {
                     return if rhs > 0 { q - 1 } else { q + 1 }
@@ -2020,11 +2044,12 @@ assert_eq!(a.rem_euclid(-b), 3);
 assert_eq!((-a).rem_euclid(-b), 1);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn rem_euclid(self, rhs: Self) -> Self {
+            pub const fn rem_euclid(self, rhs: Self) -> Self {
                 let r = self % rhs;
                 if r < 0 {
                     if rhs < 0 {
@@ -2847,10 +2872,11 @@ Basic usage:
 assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_add(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_add(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_add(rhs);
                 if b {None} else {Some(a)}
             }
@@ -2869,10 +2895,11 @@ Basic usage:
 assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_sub(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_sub(rhs);
                 if b {None} else {Some(a)}
             }
@@ -2891,10 +2918,11 @@ Basic usage:
 assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_mul(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
                 let (a, b) = self.overflowing_mul(rhs);
                 if b {None} else {Some(a)}
             }
@@ -2913,10 +2941,11 @@ Basic usage:
 assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_div(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_div(self, rhs: Self) -> Option<Self> {
                 match rhs {
                     0 => None,
                     // SAFETY: div by zero has been checked above and unsigned types have no other
@@ -2939,10 +2968,11 @@ assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));
 assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 {
                     None
                 } else {
@@ -2965,10 +2995,11 @@ Basic usage:
 assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_rem(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 {
                     None
                 } else {
@@ -2992,10 +3023,11 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
 assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
+            pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
                 if rhs == 0 {
                     None
                 } else {
@@ -3019,8 +3051,9 @@ Basic usage:
 assert_eq!(1", stringify!($SelfT), ".checked_neg(), None);", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[inline]
-            pub fn checked_neg(self) -> Option<Self> {
+            pub const fn checked_neg(self) -> Option<Self> {
                 let (a, b) = self.overflowing_neg();
                 if b {None} else {Some(a)}
             }
@@ -3039,10 +3072,11 @@ Basic usage:
 assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_shl(self, rhs: u32) -> Option<Self> {
+            pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
                 let (a, b) = self.overflowing_shl(rhs);
                 if b {None} else {Some(a)}
             }
@@ -3061,10 +3095,11 @@ Basic usage:
 assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_shr(self, rhs: u32) -> Option<Self> {
+            pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
                 let (a, b) = self.overflowing_shr(rhs);
                 if b {None} else {Some(a)}
             }
@@ -3170,11 +3205,15 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se
 "::MAX);", $EndFeature, "
 ```"),
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn saturating_mul(self, rhs: Self) -> Self {
-                self.checked_mul(rhs).unwrap_or(Self::max_value())
+            pub const fn saturating_mul(self, rhs: Self) -> Self {
+                match self.checked_mul(rhs) {
+                    Some(x) => x,
+                    None => Self::max_value(),
+                }
             }
         }
 
@@ -3289,10 +3328,11 @@ Basic usage:
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_div(self, rhs: Self) -> Self {
+            pub const fn wrapping_div(self, rhs: Self) -> Self {
                 self / rhs
             }
         }
@@ -3315,10 +3355,11 @@ Basic usage:
 assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
+            pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
                 self / rhs
             }
         }
@@ -3339,10 +3380,11 @@ Basic usage:
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, "
 ```"),
             #[stable(feature = "num_wrapping", since = "1.2.0")]
+            #[rustc_const_unstable(feature = "const_wrapping_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_rem(self, rhs: Self) -> Self {
+            pub const fn wrapping_rem(self, rhs: Self) -> Self {
                 self % rhs
             }
         }
@@ -3366,10 +3408,11 @@ Basic usage:
 assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
+            pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
                 self % rhs
             }
         }
@@ -3614,9 +3657,10 @@ Basic usage
 ```"),
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
                 (self / rhs, false)
             }
         }
@@ -3645,9 +3689,10 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
 ```"),
             #[inline]
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
                 (self / rhs, false)
             }
         }
@@ -3673,9 +3718,10 @@ Basic usage
 ```"),
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
+            #[rustc_const_unstable(feature = "const_overflowing_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
                 (self % rhs, false)
             }
         }
@@ -3704,9 +3750,10 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
 ```"),
             #[inline]
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
-            pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
+            pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
                 (self % rhs, false)
             }
         }
@@ -3897,11 +3944,12 @@ Basic usage:
 assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn div_euclid(self, rhs: Self) -> Self {
+            pub const fn div_euclid(self, rhs: Self) -> Self {
                 self / rhs
             }
         }
@@ -3926,11 +3974,12 @@ Basic usage:
 assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type
 ```"),
             #[stable(feature = "euclidean_division", since = "1.38.0")]
+            #[rustc_const_unstable(feature = "const_euclidean_int_methods", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn rem_euclid(self, rhs: Self) -> Self {
+            pub const fn rem_euclid(self, rhs: Self) -> Self {
                 self % rhs
             }
         }
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 15e92d8d842..92f5bf87535 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -216,6 +216,7 @@ arena_types!(declare_arena, [], 'tcx);
 
 arena_types!(impl_arena_allocatable, [], 'tcx);
 
+#[marker]
 pub trait ArenaAllocatable {}
 
 impl<T: Copy> ArenaAllocatable for T {}
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 061b82ebb43..01558615497 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -40,40 +40,14 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
         }
     }
 
-    // The following implementations of HashStable for `ItemId`, `TraitItemId`, and
-    // `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
-    // the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
-    // are used when another item in the HIR is *referenced* and we certainly
-    // want to pick up on a reference changing its target, so we hash the NodeIds
-    // in "DefPath Mode".
-
-    fn hash_item_id(&mut self, id: hir::ItemId, hasher: &mut StableHasher) {
+    fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) {
         let hcx = self;
-        let hir::ItemId { id } = id;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             id.hash_stable(hcx, hasher);
         })
     }
 
-    fn hash_impl_item_id(&mut self, id: hir::ImplItemId, hasher: &mut StableHasher) {
-        let hcx = self;
-        let hir::ImplItemId { hir_id } = id;
-
-        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            hir_id.hash_stable(hcx, hasher);
-        })
-    }
-
-    fn hash_trait_item_id(&mut self, id: hir::TraitItemId, hasher: &mut StableHasher) {
-        let hcx = self;
-        let hir::TraitItemId { hir_id } = id;
-
-        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
-            hir_id.hash_stable(hcx, hasher);
-        })
-    }
-
     fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) {
         let hcx = self;
         let hir::Mod { inner: ref inner_span, ref item_ids } = *module;
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index a588d3d028a..f157d805bcd 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -21,18 +21,15 @@
 //!
 //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 
-use crate::infer::region_constraints::MemberConstraint;
 use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
 use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
-use crate::ty::fold::TypeFoldable;
-use crate::ty::subst::GenericArg;
-use crate::ty::{self, BoundVar, List, Region, TyCtxt};
+use rustc::ty::fold::TypeFoldable;
+use rustc::ty::subst::GenericArg;
+use rustc::ty::{self, BoundVar, List};
 use rustc_index::vec::IndexVec;
-use rustc_macros::HashStable;
-use rustc_serialize::UseSpecializedDecodable;
 use rustc_span::source_map::Span;
-use smallvec::SmallVec;
-use std::ops::Index;
+
+pub use rustc::infer::types::canonical::*;
 
 mod canonicalizer;
 
@@ -40,265 +37,6 @@ pub mod query_response;
 
 mod substitute;
 
-/// A "canonicalized" type `V` is one where all free inference
-/// variables have been rewritten to "canonical vars". These are
-/// numbered starting from 0 in order of first appearance.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable, TypeFoldable, Lift)]
-pub struct Canonical<'tcx, V> {
-    pub max_universe: ty::UniverseIndex,
-    pub variables: CanonicalVarInfos<'tcx>,
-    pub value: V,
-}
-
-pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>;
-
-impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
-
-/// A set of values corresponding to the canonical variables from some
-/// `Canonical`. You can give these values to
-/// `canonical_value.substitute` to substitute them into the canonical
-/// value at the right places.
-///
-/// When you canonicalize a value `V`, you get back one of these
-/// vectors with the original values that were replaced by canonical
-/// variables. You will need to supply it later to instantiate the
-/// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable, TypeFoldable, Lift)]
-pub struct CanonicalVarValues<'tcx> {
-    pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
-}
-
-/// When we canonicalize a value to form a query, we wind up replacing
-/// various parts of it with canonical variables. This struct stores
-/// those replaced bits to remember for when we process the query
-/// result.
-#[derive(Clone, Debug)]
-pub struct OriginalQueryValues<'tcx> {
-    /// Map from the universes that appear in the query to the
-    /// universes in the caller context. For the time being, we only
-    /// ever put ROOT values into the query, so this map is very
-    /// simple.
-    pub universe_map: SmallVec<[ty::UniverseIndex; 4]>,
-
-    /// This is equivalent to `CanonicalVarValues`, but using a
-    /// `SmallVec` yields a significant performance win.
-    pub var_values: SmallVec<[GenericArg<'tcx>; 8]>,
-}
-
-impl Default for OriginalQueryValues<'tcx> {
-    fn default() -> Self {
-        let mut universe_map = SmallVec::default();
-        universe_map.push(ty::UniverseIndex::ROOT);
-
-        Self { universe_map, var_values: SmallVec::default() }
-    }
-}
-
-/// Information about a canonical variable that is included with the
-/// canonical value. This is sufficient information for code to create
-/// a copy of the canonical value in some other inference context,
-/// with fresh inference variables replacing the canonical values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
-pub struct CanonicalVarInfo {
-    pub kind: CanonicalVarKind,
-}
-
-impl CanonicalVarInfo {
-    pub fn universe(&self) -> ty::UniverseIndex {
-        self.kind.universe()
-    }
-
-    pub fn is_existential(&self) -> bool {
-        match self.kind {
-            CanonicalVarKind::Ty(_) => true,
-            CanonicalVarKind::PlaceholderTy(_) => false,
-            CanonicalVarKind::Region(_) => true,
-            CanonicalVarKind::PlaceholderRegion(..) => false,
-            CanonicalVarKind::Const(_) => true,
-            CanonicalVarKind::PlaceholderConst(_) => false,
-        }
-    }
-}
-
-/// Describes the "kind" of the canonical variable. This is a "kind"
-/// in the type-theory sense of the term -- i.e., a "meta" type system
-/// that analyzes type-like values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
-pub enum CanonicalVarKind {
-    /// Some kind of type inference variable.
-    Ty(CanonicalTyVarKind),
-
-    /// A "placeholder" that represents "any type".
-    PlaceholderTy(ty::PlaceholderType),
-
-    /// Region variable `'?R`.
-    Region(ty::UniverseIndex),
-
-    /// A "placeholder" that represents "any region". Created when you
-    /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
-    /// bound region `'a`.
-    PlaceholderRegion(ty::PlaceholderRegion),
-
-    /// Some kind of const inference variable.
-    Const(ty::UniverseIndex),
-
-    /// A "placeholder" that represents "any const".
-    PlaceholderConst(ty::PlaceholderConst),
-}
-
-impl CanonicalVarKind {
-    pub fn universe(self) -> ty::UniverseIndex {
-        match self {
-            CanonicalVarKind::Ty(kind) => match kind {
-                CanonicalTyVarKind::General(ui) => ui,
-                CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
-            },
-
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
-            CanonicalVarKind::Region(ui) => ui,
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
-            CanonicalVarKind::Const(ui) => ui,
-            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe,
-        }
-    }
-}
-
-/// Rust actually has more than one category of type variables;
-/// notably, the type variables we create for literals (e.g., 22 or
-/// 22.) can only be instantiated with integral/float types (e.g.,
-/// usize or f32). In order to faithfully reproduce a type, we need to
-/// know what set of types a given type variable can be unified with.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
-pub enum CanonicalTyVarKind {
-    /// General type variable `?T` that can be unified with arbitrary types.
-    General(ty::UniverseIndex),
-
-    /// Integral type variable `?I` (that can only be unified with integral types).
-    Int,
-
-    /// Floating-point type variable `?F` (that can only be unified with float types).
-    Float,
-}
-
-/// After we execute a query with a canonicalized key, we get back a
-/// `Canonical<QueryResponse<..>>`. You can use
-/// `instantiate_query_result` to access the data in this result.
-#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct QueryResponse<'tcx, R> {
-    pub var_values: CanonicalVarValues<'tcx>,
-    pub region_constraints: QueryRegionConstraints<'tcx>,
-    pub certainty: Certainty,
-    pub value: R,
-}
-
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
-pub struct QueryRegionConstraints<'tcx> {
-    pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
-    pub member_constraints: Vec<MemberConstraint<'tcx>>,
-}
-
-impl QueryRegionConstraints<'_> {
-    /// Represents an empty (trivially true) set of region
-    /// constraints.
-    pub fn is_empty(&self) -> bool {
-        self.outlives.is_empty() && self.member_constraints.is_empty()
-    }
-}
-
-pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
-
-pub type CanonicalizedQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
-
-/// Indicates whether or not we were able to prove the query to be
-/// true.
-#[derive(Copy, Clone, Debug, HashStable)]
-pub enum Certainty {
-    /// The query is known to be true, presuming that you apply the
-    /// given `var_values` and the region-constraints are satisfied.
-    Proven,
-
-    /// The query is not known to be true, but also not known to be
-    /// false. The `var_values` represent *either* values that must
-    /// hold in order for the query to be true, or helpful tips that
-    /// *might* make it true. Currently rustc's trait solver cannot
-    /// distinguish the two (e.g., due to our preference for where
-    /// clauses over impls).
-    ///
-    /// After some unifiations and things have been done, it makes
-    /// sense to try and prove again -- of course, at that point, the
-    /// canonical form will be different, making this a distinct
-    /// query.
-    Ambiguous,
-}
-
-impl Certainty {
-    pub fn is_proven(&self) -> bool {
-        match self {
-            Certainty::Proven => true,
-            Certainty::Ambiguous => false,
-        }
-    }
-
-    pub fn is_ambiguous(&self) -> bool {
-        !self.is_proven()
-    }
-}
-
-impl<'tcx, R> QueryResponse<'tcx, R> {
-    pub fn is_proven(&self) -> bool {
-        self.certainty.is_proven()
-    }
-
-    pub fn is_ambiguous(&self) -> bool {
-        !self.is_proven()
-    }
-}
-
-impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
-    pub fn is_proven(&self) -> bool {
-        self.value.is_proven()
-    }
-
-    pub fn is_ambiguous(&self) -> bool {
-        !self.is_proven()
-    }
-}
-
-impl<'tcx, V> Canonical<'tcx, V> {
-    /// Allows you to map the `value` of a canonical while keeping the
-    /// same set of bound variables.
-    ///
-    /// **WARNING:** This function is very easy to mis-use, hence the
-    /// name!  In particular, the new value `W` must use all **the
-    /// same type/region variables** in **precisely the same order**
-    /// as the original! (The ordering is defined by the
-    /// `TypeFoldable` implementation of the type in question.)
-    ///
-    /// An example of a **correct** use of this:
-    ///
-    /// ```rust,ignore (not real code)
-    /// let a: Canonical<'_, T> = ...;
-    /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
-    /// ```
-    ///
-    /// An example of an **incorrect** use of this:
-    ///
-    /// ```rust,ignore (not real code)
-    /// let a: Canonical<'tcx, T> = ...;
-    /// let ty: Ty<'tcx> = ...;
-    /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
-    /// ```
-    pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W> {
-        let Canonical { max_universe, variables, value } = self;
-        Canonical { max_universe, variables, value: map_op(value) }
-    }
-}
-
-pub type QueryOutlivesConstraint<'tcx> =
-    ty::Binder<ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>;
-
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Creates a substitution S for the canonical value with fresh
     /// inference variables and applies it to the canonical value.
@@ -424,70 +162,3 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         }
     }
 }
-
-CloneTypeFoldableAndLiftImpls! {
-    crate::infer::canonical::Certainty,
-    crate::infer::canonical::CanonicalVarInfo,
-    crate::infer::canonical::CanonicalVarKind,
-}
-
-CloneTypeFoldableImpls! {
-    for <'tcx> {
-        crate::infer::canonical::CanonicalVarInfos<'tcx>,
-    }
-}
-
-impl<'tcx> CanonicalVarValues<'tcx> {
-    pub fn len(&self) -> usize {
-        self.var_values.len()
-    }
-
-    /// Makes an identity substitution from this one: each bound var
-    /// is matched to the same bound var, preserving the original kinds.
-    /// For example, if we have:
-    /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
-    /// we'll return a substitution `subst` with:
-    /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
-    pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
-        use crate::ty::subst::GenericArgKind;
-
-        CanonicalVarValues {
-            var_values: self
-                .var_values
-                .iter()
-                .zip(0..)
-                .map(|(kind, i)| match kind.unpack() {
-                    GenericArgKind::Type(..) => {
-                        tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
-                    }
-                    GenericArgKind::Lifetime(..) => tcx
-                        .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i)))
-                        .into(),
-                    GenericArgKind::Const(ct) => tcx
-                        .mk_const(ty::Const {
-                            ty: ct.ty,
-                            val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
-                        })
-                        .into(),
-                })
-                .collect(),
-        }
-    }
-}
-
-impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
-    type Item = GenericArg<'tcx>;
-    type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        self.var_values.iter().cloned()
-    }
-}
-
-impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
-    type Output = GenericArg<'tcx>;
-
-    fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
-        &self.var_values[value]
-    }
-}
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f67669e367f..4681a47317c 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -61,6 +61,7 @@ pub mod region_constraints;
 pub mod resolve;
 mod sub;
 pub mod type_variable;
+mod types;
 pub mod unify_key;
 
 #[must_use]
@@ -556,16 +557,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     }
 }
 
-impl<T> ExpectedFound<T> {
-    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
-        if a_is_expected {
-            ExpectedFound { expected: a, found: b }
-        } else {
-            ExpectedFound { expected: b, found: a }
-        }
-    }
-}
-
 impl<'tcx, T> InferOk<'tcx, T> {
     pub fn unit(self) -> InferOk<'tcx, ()> {
         InferOk { value: (), obligations: self.obligations }
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 27ed3c78138..410058b70b5 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -23,6 +23,8 @@ use std::{cmp, fmt, mem};
 
 mod leak_check;
 
+pub use rustc::infer::types::MemberConstraint;
+
 #[derive(Default)]
 pub struct RegionConstraintCollector<'tcx> {
     /// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
@@ -145,30 +147,6 @@ impl Constraint<'_> {
     }
 }
 
-/// Requires that `region` must be equal to one of the regions in `choice_regions`.
-/// We often denote this using the syntax:
-///
-/// ```
-/// R0 member of [O1..On]
-/// ```
-#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
-pub struct MemberConstraint<'tcx> {
-    /// The `DefId` of the opaque type causing this constraint: used for error reporting.
-    pub opaque_type_def_id: DefId,
-
-    /// The span where the hidden type was instantiated.
-    pub definition_span: Span,
-
-    /// The hidden type in which `member_region` appears: used for error reporting.
-    pub hidden_ty: Ty<'tcx>,
-
-    /// The region `R0`.
-    pub member_region: Region<'tcx>,
-
-    /// The options `O1..On`.
-    pub choice_regions: Lrc<Vec<Region<'tcx>>>,
-}
-
 /// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
 /// associated type) must outlive the region `R`. `T` is known to
 /// outlive `RS`. Therefore, verify that `R <= RS[i]` for some
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 8ea1b705d44..f391a054a2a 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -453,18 +453,3 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
         }
     }
 }
-
-/// Raw `TyVid` are used as the unification key for `sub_relations`;
-/// they carry no values.
-impl ut::UnifyKey for ty::TyVid {
-    type Value = ();
-    fn index(&self) -> u32 {
-        self.index
-    }
-    fn from_index(i: u32) -> ty::TyVid {
-        ty::TyVid { index: i }
-    }
-    fn tag() -> &'static str {
-        "TyVid"
-    }
-}
diff --git a/src/librustc/infer/types/canonical.rs b/src/librustc/infer/types/canonical.rs
new file mode 100644
index 00000000000..133cf1b5928
--- /dev/null
+++ b/src/librustc/infer/types/canonical.rs
@@ -0,0 +1,357 @@
+//! **Canonicalization** is the key to constructing a query in the
+//! middle of type inference. Ordinarily, it is not possible to store
+//! types from type inference in query keys, because they contain
+//! references to inference variables whose lifetimes are too short
+//! and so forth. Canonicalizing a value T1 using `canonicalize_query`
+//! produces two things:
+//!
+//! - a value T2 where each unbound inference variable has been
+//!   replaced with a **canonical variable**;
+//! - a map M (of type `CanonicalVarValues`) from those canonical
+//!   variables back to the original.
+//!
+//! We can then do queries using T2. These will give back constraints
+//! on the canonical variables which can be translated, using the map
+//! M, into constraints in our source context. This process of
+//! translating the results back is done by the
+//! `instantiate_query_result` method.
+//!
+//! For a more detailed look at what is happening here, check
+//! out the [chapter in the rustc guide][c].
+//!
+//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
+
+use crate::infer::region_constraints::MemberConstraint;
+use crate::ty::subst::GenericArg;
+use crate::ty::{self, BoundVar, List, Region, TyCtxt};
+use rustc_index::vec::IndexVec;
+use rustc_macros::HashStable;
+use rustc_serialize::UseSpecializedDecodable;
+use smallvec::SmallVec;
+use std::ops::Index;
+
+/// A "canonicalized" type `V` is one where all free inference
+/// variables have been rewritten to "canonical vars". These are
+/// numbered starting from 0 in order of first appearance.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(HashStable, TypeFoldable, Lift)]
+pub struct Canonical<'tcx, V> {
+    pub max_universe: ty::UniverseIndex,
+    pub variables: CanonicalVarInfos<'tcx>,
+    pub value: V,
+}
+
+pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>;
+
+impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
+
+/// A set of values corresponding to the canonical variables from some
+/// `Canonical`. You can give these values to
+/// `canonical_value.substitute` to substitute them into the canonical
+/// value at the right places.
+///
+/// When you canonicalize a value `V`, you get back one of these
+/// vectors with the original values that were replaced by canonical
+/// variables. You will need to supply it later to instantiate the
+/// canonicalized query response.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(HashStable, TypeFoldable, Lift)]
+pub struct CanonicalVarValues<'tcx> {
+    pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
+}
+
+/// When we canonicalize a value to form a query, we wind up replacing
+/// various parts of it with canonical variables. This struct stores
+/// those replaced bits to remember for when we process the query
+/// result.
+#[derive(Clone, Debug)]
+pub struct OriginalQueryValues<'tcx> {
+    /// Map from the universes that appear in the query to the
+    /// universes in the caller context. For the time being, we only
+    /// ever put ROOT values into the query, so this map is very
+    /// simple.
+    pub universe_map: SmallVec<[ty::UniverseIndex; 4]>,
+
+    /// This is equivalent to `CanonicalVarValues`, but using a
+    /// `SmallVec` yields a significant performance win.
+    pub var_values: SmallVec<[GenericArg<'tcx>; 8]>,
+}
+
+impl Default for OriginalQueryValues<'tcx> {
+    fn default() -> Self {
+        let mut universe_map = SmallVec::default();
+        universe_map.push(ty::UniverseIndex::ROOT);
+
+        Self { universe_map, var_values: SmallVec::default() }
+    }
+}
+
+/// Information about a canonical variable that is included with the
+/// canonical value. This is sufficient information for code to create
+/// a copy of the canonical value in some other inference context,
+/// with fresh inference variables replacing the canonical values.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+pub struct CanonicalVarInfo {
+    pub kind: CanonicalVarKind,
+}
+
+impl CanonicalVarInfo {
+    pub fn universe(&self) -> ty::UniverseIndex {
+        self.kind.universe()
+    }
+
+    pub fn is_existential(&self) -> bool {
+        match self.kind {
+            CanonicalVarKind::Ty(_) => true,
+            CanonicalVarKind::PlaceholderTy(_) => false,
+            CanonicalVarKind::Region(_) => true,
+            CanonicalVarKind::PlaceholderRegion(..) => false,
+            CanonicalVarKind::Const(_) => true,
+            CanonicalVarKind::PlaceholderConst(_) => false,
+        }
+    }
+}
+
+/// Describes the "kind" of the canonical variable. This is a "kind"
+/// in the type-theory sense of the term -- i.e., a "meta" type system
+/// that analyzes type-like values.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+pub enum CanonicalVarKind {
+    /// Some kind of type inference variable.
+    Ty(CanonicalTyVarKind),
+
+    /// A "placeholder" that represents "any type".
+    PlaceholderTy(ty::PlaceholderType),
+
+    /// Region variable `'?R`.
+    Region(ty::UniverseIndex),
+
+    /// A "placeholder" that represents "any region". Created when you
+    /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
+    /// bound region `'a`.
+    PlaceholderRegion(ty::PlaceholderRegion),
+
+    /// Some kind of const inference variable.
+    Const(ty::UniverseIndex),
+
+    /// A "placeholder" that represents "any const".
+    PlaceholderConst(ty::PlaceholderConst),
+}
+
+impl CanonicalVarKind {
+    pub fn universe(self) -> ty::UniverseIndex {
+        match self {
+            CanonicalVarKind::Ty(kind) => match kind {
+                CanonicalTyVarKind::General(ui) => ui,
+                CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
+            },
+
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
+            CanonicalVarKind::Region(ui) => ui,
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
+            CanonicalVarKind::Const(ui) => ui,
+            CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe,
+        }
+    }
+}
+
+/// Rust actually has more than one category of type variables;
+/// notably, the type variables we create for literals (e.g., 22 or
+/// 22.) can only be instantiated with integral/float types (e.g.,
+/// usize or f32). In order to faithfully reproduce a type, we need to
+/// know what set of types a given type variable can be unified with.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+pub enum CanonicalTyVarKind {
+    /// General type variable `?T` that can be unified with arbitrary types.
+    General(ty::UniverseIndex),
+
+    /// Integral type variable `?I` (that can only be unified with integral types).
+    Int,
+
+    /// Floating-point type variable `?F` (that can only be unified with float types).
+    Float,
+}
+
+/// After we execute a query with a canonicalized key, we get back a
+/// `Canonical<QueryResponse<..>>`. You can use
+/// `instantiate_query_result` to access the data in this result.
+#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
+pub struct QueryResponse<'tcx, R> {
+    pub var_values: CanonicalVarValues<'tcx>,
+    pub region_constraints: QueryRegionConstraints<'tcx>,
+    pub certainty: Certainty,
+    pub value: R,
+}
+
+#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
+pub struct QueryRegionConstraints<'tcx> {
+    pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
+    pub member_constraints: Vec<MemberConstraint<'tcx>>,
+}
+
+impl QueryRegionConstraints<'_> {
+    /// Represents an empty (trivially true) set of region
+    /// constraints.
+    pub fn is_empty(&self) -> bool {
+        self.outlives.is_empty() && self.member_constraints.is_empty()
+    }
+}
+
+pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
+
+pub type CanonicalizedQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
+
+/// Indicates whether or not we were able to prove the query to be
+/// true.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub enum Certainty {
+    /// The query is known to be true, presuming that you apply the
+    /// given `var_values` and the region-constraints are satisfied.
+    Proven,
+
+    /// The query is not known to be true, but also not known to be
+    /// false. The `var_values` represent *either* values that must
+    /// hold in order for the query to be true, or helpful tips that
+    /// *might* make it true. Currently rustc's trait solver cannot
+    /// distinguish the two (e.g., due to our preference for where
+    /// clauses over impls).
+    ///
+    /// After some unifiations and things have been done, it makes
+    /// sense to try and prove again -- of course, at that point, the
+    /// canonical form will be different, making this a distinct
+    /// query.
+    Ambiguous,
+}
+
+impl Certainty {
+    pub fn is_proven(&self) -> bool {
+        match self {
+            Certainty::Proven => true,
+            Certainty::Ambiguous => false,
+        }
+    }
+
+    pub fn is_ambiguous(&self) -> bool {
+        !self.is_proven()
+    }
+}
+
+impl<'tcx, R> QueryResponse<'tcx, R> {
+    pub fn is_proven(&self) -> bool {
+        self.certainty.is_proven()
+    }
+
+    pub fn is_ambiguous(&self) -> bool {
+        !self.is_proven()
+    }
+}
+
+impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
+    pub fn is_proven(&self) -> bool {
+        self.value.is_proven()
+    }
+
+    pub fn is_ambiguous(&self) -> bool {
+        !self.is_proven()
+    }
+}
+
+impl<'tcx, V> Canonical<'tcx, V> {
+    /// Allows you to map the `value` of a canonical while keeping the
+    /// same set of bound variables.
+    ///
+    /// **WARNING:** This function is very easy to mis-use, hence the
+    /// name!  In particular, the new value `W` must use all **the
+    /// same type/region variables** in **precisely the same order**
+    /// as the original! (The ordering is defined by the
+    /// `TypeFoldable` implementation of the type in question.)
+    ///
+    /// An example of a **correct** use of this:
+    ///
+    /// ```rust,ignore (not real code)
+    /// let a: Canonical<'_, T> = ...;
+    /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
+    /// ```
+    ///
+    /// An example of an **incorrect** use of this:
+    ///
+    /// ```rust,ignore (not real code)
+    /// let a: Canonical<'tcx, T> = ...;
+    /// let ty: Ty<'tcx> = ...;
+    /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
+    /// ```
+    pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W> {
+        let Canonical { max_universe, variables, value } = self;
+        Canonical { max_universe, variables, value: map_op(value) }
+    }
+}
+
+pub type QueryOutlivesConstraint<'tcx> =
+    ty::Binder<ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>;
+
+CloneTypeFoldableAndLiftImpls! {
+    crate::infer::canonical::Certainty,
+    crate::infer::canonical::CanonicalVarInfo,
+    crate::infer::canonical::CanonicalVarKind,
+}
+
+CloneTypeFoldableImpls! {
+    for <'tcx> {
+        crate::infer::canonical::CanonicalVarInfos<'tcx>,
+    }
+}
+
+impl<'tcx> CanonicalVarValues<'tcx> {
+    pub fn len(&self) -> usize {
+        self.var_values.len()
+    }
+
+    /// Makes an identity substitution from this one: each bound var
+    /// is matched to the same bound var, preserving the original kinds.
+    /// For example, if we have:
+    /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
+    /// we'll return a substitution `subst` with:
+    /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
+    pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
+        use crate::ty::subst::GenericArgKind;
+
+        CanonicalVarValues {
+            var_values: self
+                .var_values
+                .iter()
+                .zip(0..)
+                .map(|(kind, i)| match kind.unpack() {
+                    GenericArgKind::Type(..) => {
+                        tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
+                    }
+                    GenericArgKind::Lifetime(..) => tcx
+                        .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i)))
+                        .into(),
+                    GenericArgKind::Const(ct) => tcx
+                        .mk_const(ty::Const {
+                            ty: ct.ty,
+                            val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
+                        })
+                        .into(),
+                })
+                .collect(),
+        }
+    }
+}
+
+impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
+    type Item = GenericArg<'tcx>;
+    type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.var_values.iter().cloned()
+    }
+}
+
+impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
+    type Output = GenericArg<'tcx>;
+
+    fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
+        &self.var_values[value]
+    }
+}
diff --git a/src/librustc/infer/types/mod.rs b/src/librustc/infer/types/mod.rs
new file mode 100644
index 00000000000..534f4cb179c
--- /dev/null
+++ b/src/librustc/infer/types/mod.rs
@@ -0,0 +1,31 @@
+pub mod canonical;
+
+use crate::ty::Region;
+use crate::ty::Ty;
+use rustc_data_structures::sync::Lrc;
+use rustc_hir::def_id::DefId;
+use rustc_span::Span;
+
+/// Requires that `region` must be equal to one of the regions in `choice_regions`.
+/// We often denote this using the syntax:
+///
+/// ```
+/// R0 member of [O1..On]
+/// ```
+#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
+pub struct MemberConstraint<'tcx> {
+    /// The `DefId` of the opaque type causing this constraint: used for error reporting.
+    pub opaque_type_def_id: DefId,
+
+    /// The span where the hidden type was instantiated.
+    pub definition_span: Span,
+
+    /// The hidden type in which `member_region` appears: used for error reporting.
+    pub hidden_ty: Ty<'tcx>,
+
+    /// The region `R0`.
+    pub member_region: Region<'tcx>,
+
+    /// The options `O1..On`.
+    pub choice_regions: Lrc<Vec<Region<'tcx>>>,
+}
diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs
index c5ec0ba73e4..d88188538fc 100644
--- a/src/librustc/infer/unify_key.rs
+++ b/src/librustc/infer/unify_key.rs
@@ -12,6 +12,21 @@ pub trait ToType {
     fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
 }
 
+/// Raw `TyVid` are used as the unification key for `sub_relations`;
+/// they carry no values.
+impl UnifyKey for ty::TyVid {
+    type Value = ();
+    fn index(&self) -> u32 {
+        self.index
+    }
+    fn from_index(i: u32) -> ty::TyVid {
+        ty::TyVid { index: i }
+    }
+    fn tag() -> &'static str {
+        "TyVid"
+    }
+}
+
 impl UnifyKey for ty::IntVid {
     type Value = Option<IntVarValue>;
     fn index(&self) -> u32 {
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 744ee1a65e1..2f77792f7a1 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -36,7 +36,7 @@
 #![feature(drain_filter)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
-#![feature(overlapping_marker_traits)]
+#![feature(marker_trait_attr)]
 #![feature(extern_types)]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 37d5e23535b..228271e0c4c 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -310,6 +310,11 @@ rustc_queries! {
         /// Maps from a trait item to the trait item "descriptor".
         query associated_item(_: DefId) -> ty::AssocItem {}
 
+        /// Collects the associated items defined on a trait or impl.
+        query associated_items(key: DefId) -> ty::AssocItemsIterator<'tcx> {
+            desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
+        }
+
         query impl_trait_ref(_: DefId) -> Option<ty::TraitRef<'tcx>> {}
         query impl_polarity(_: DefId) -> ty::ImplPolarity {}
 
diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index fdb6432f7c9..d775393a808 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -9,6 +9,7 @@ use crate::ty::fold::TypeFolder;
 use crate::ty::{Region, RegionVid};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use syntax::ast;
 
 use std::collections::hash_map::Entry;
 use std::collections::VecDeque;
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
index c1facd34dfe..b2973c642a2 100644
--- a/src/librustc/traits/error_reporting/suggestions.rs
+++ b/src/librustc/traits/error_reporting/suggestions.rs
@@ -1646,8 +1646,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let current_limit = self.tcx.sess.recursion_limit.get();
         let suggested_limit = current_limit * 2;
         err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+            suggested_limit, self.tcx.crate_name,
         ));
     }
 }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index daaba95cf6b..e88f4e65c7e 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -19,32 +19,25 @@ mod select;
 mod specialize;
 mod structural_impls;
 mod structural_match;
+mod types;
 mod util;
 pub mod wf;
 
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, SuppressRegionErrors};
 use crate::middle::region;
-use crate::mir::interpret::ErrorHandled;
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::{InternalSubsts, SubstsRef};
-use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
+use crate::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
 use crate::util::common::ErrorReported;
-use chalk_engine;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_macros::HashStable;
 use rustc_span::{Span, DUMMY_SP};
-use syntax::ast;
 
 use std::fmt::Debug;
-use std::rc::Rc;
 
 pub use self::FulfillmentErrorCode::*;
-pub use self::ObligationCauseCode::*;
-pub use self::SelectionError::*;
-pub use self::Vtable::*;
 
 pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
 pub use self::coherence::{OrphanCheckErr, OverlapResult};
@@ -58,9 +51,8 @@ pub use self::object_safety::ObjectSafetyViolation;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};
-pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal};
-pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
-pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
+pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot};
+pub use self::select::{IntercrateAmbiguityCause, SelectionContext};
 pub use self::specialize::find_associated_item;
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
@@ -82,10 +74,7 @@ pub use self::chalk_fulfill::{
     CanonicalGoal as ChalkCanonicalGoal, FulfillmentContext as ChalkFulfillmentContext,
 };
 
-pub use self::FulfillmentErrorCode::*;
-pub use self::ObligationCauseCode::*;
-pub use self::SelectionError::*;
-pub use self::Vtable::*;
+pub use self::types::*;
 
 /// Whether to enable bug compatibility with issue #43355.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -139,392 +128,12 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(PredicateObligation<'_>, 112);
 
-/// The reason why we incurred this obligation; used for error reporting.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct ObligationCause<'tcx> {
-    pub span: Span,
-
-    /// The ID of the fn body that triggered this obligation. This is
-    /// used for region obligations to determine the precise
-    /// environment in which the region obligation should be evaluated
-    /// (in particular, closures can add new assumptions). See the
-    /// field `region_obligations` of the `FulfillmentContext` for more
-    /// information.
-    pub body_id: hir::HirId,
-
-    pub code: ObligationCauseCode<'tcx>,
-}
-
-impl ObligationCause<'_> {
-    pub fn span(&self, tcx: TyCtxt<'_>) -> Span {
-        match self.code {
-            ObligationCauseCode::CompareImplMethodObligation { .. }
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType => tcx.sess.source_map().def_span(self.span),
-            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                arm_span,
-                ..
-            }) => arm_span,
-            _ => self.span,
-        }
-    }
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum ObligationCauseCode<'tcx> {
-    /// Not well classified or should be obvious from the span.
-    MiscObligation,
-
-    /// A slice or array is WF only if `T: Sized`.
-    SliceOrArrayElem,
-
-    /// A tuple is WF only if its middle elements are `Sized`.
-    TupleElem,
-
-    /// This is the trait reference from the given projection.
-    ProjectionWf(ty::ProjectionTy<'tcx>),
-
-    /// In an impl of trait `X` for type `Y`, type `Y` must
-    /// also implement all supertraits of `X`.
-    ItemObligation(DefId),
-
-    /// Like `ItemObligation`, but with extra detail on the source of the obligation.
-    BindingObligation(DefId, Span),
-
-    /// A type like `&'a T` is WF only if `T: 'a`.
-    ReferenceOutlivesReferent(Ty<'tcx>),
-
-    /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
-    ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
-
-    /// Obligation incurred due to an object cast.
-    ObjectCastObligation(/* Object type */ Ty<'tcx>),
-
-    /// Obligation incurred due to a coercion.
-    Coercion {
-        source: Ty<'tcx>,
-        target: Ty<'tcx>,
-    },
-
-    /// Various cases where expressions must be `Sized` / `Copy` / etc.
-    /// `L = X` implies that `L` is `Sized`.
-    AssignmentLhsSized,
-    /// `(x1, .., xn)` must be `Sized`.
-    TupleInitializerSized,
-    /// `S { ... }` must be `Sized`.
-    StructInitializerSized,
-    /// Type of each variable must be `Sized`.
-    VariableType(hir::HirId),
-    /// Argument type must be `Sized`.
-    SizedArgumentType,
-    /// Return type must be `Sized`.
-    SizedReturnType,
-    /// Yield type must be `Sized`.
-    SizedYieldType,
-    /// `[T, ..n]` implies that `T` must be `Copy`.
-    /// If `true`, suggest `const_in_array_repeat_expressions` feature flag.
-    RepeatVec(bool),
-
-    /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
-    FieldSized {
-        adt_kind: AdtKind,
-        last: bool,
-    },
-
-    /// Constant expressions must be sized.
-    ConstSized,
-
-    /// `static` items must have `Sync` type.
-    SharedStatic,
-
-    BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
-
-    ImplDerivedObligation(DerivedObligationCause<'tcx>),
-
-    /// Error derived when matching traits/impls; see ObligationCause for more details
-    CompareImplMethodObligation {
-        item_name: ast::Name,
-        impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-    },
-
-    /// Error derived when matching traits/impls; see ObligationCause for more details
-    CompareImplTypeObligation {
-        item_name: ast::Name,
-        impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-    },
-
-    /// Checking that this expression can be assigned where it needs to be
-    // FIXME(eddyb) #11161 is the original Expr required?
-    ExprAssignable,
-
-    /// Computing common supertype in the arms of a match expression
-    MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
-
-    /// Type error arising from type checking a pattern against an expected type.
-    Pattern {
-        /// The span of the scrutinee or type expression which caused the `root_ty` type.
-        span: Option<Span>,
-        /// The root expected type induced by a scrutinee or type expression.
-        root_ty: Ty<'tcx>,
-        /// Whether the `Span` came from an expression or a type expression.
-        origin_expr: bool,
-    },
-
-    /// Constants in patterns must have `Structural` type.
-    ConstPatternStructural,
-
-    /// Computing common supertype in an if expression
-    IfExpression(Box<IfExpressionCause>),
-
-    /// Computing common supertype of an if expression with no else counter-part
-    IfExpressionWithNoElse,
-
-    /// `main` has wrong type
-    MainFunctionType,
-
-    /// `start` has wrong type
-    StartFunctionType,
-
-    /// Intrinsic has wrong type
-    IntrinsicType,
-
-    /// Method receiver
-    MethodReceiver,
-
-    /// `return` with no expression
-    ReturnNoExpression,
-
-    /// `return` with an expression
-    ReturnValue(hir::HirId),
-
-    /// Return type of this function
-    ReturnType,
-
-    /// Block implicit return
-    BlockTailExpression(hir::HirId),
-
-    /// #[feature(trivial_bounds)] is not enabled
-    TrivialBound,
-
-    AssocTypeBound(Box<AssocTypeBoundData>),
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct AssocTypeBoundData {
-    pub impl_span: Option<Span>,
-    pub original: Span,
-    pub bounds: Vec<Span>,
-}
-
-// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-static_assert_size!(ObligationCauseCode<'_>, 32);
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct MatchExpressionArmCause<'tcx> {
-    pub arm_span: Span,
-    pub source: hir::MatchSource,
-    pub prior_arms: Vec<Span>,
-    pub last_ty: Ty<'tcx>,
-    pub scrut_hir_id: hir::HirId,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct IfExpressionCause {
-    pub then: Span,
-    pub outer: Option<Span>,
-    pub semicolon: Option<Span>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DerivedObligationCause<'tcx> {
-    /// The trait reference of the parent obligation that led to the
-    /// current obligation. Note that only trait obligations lead to
-    /// derived obligations, so we just store the trait reference here
-    /// directly.
-    parent_trait_ref: ty::PolyTraitRef<'tcx>,
-
-    /// The parent trait had this cause.
-    parent_code: Rc<ObligationCauseCode<'tcx>>,
-}
-
 pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
 pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
 pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
 
-/// The following types:
-/// * `WhereClause`,
-/// * `WellFormed`,
-/// * `FromEnv`,
-/// * `DomainGoal`,
-/// * `Goal`,
-/// * `Clause`,
-/// * `Environment`,
-/// * `InEnvironment`,
-/// are used for representing the trait system in the form of
-/// logic programming clauses. They are part of the interface
-/// for the chalk SLG solver.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
-pub enum WhereClause<'tcx> {
-    Implemented(ty::TraitPredicate<'tcx>),
-    ProjectionEq(ty::ProjectionPredicate<'tcx>),
-    RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
-    TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
-pub enum WellFormed<'tcx> {
-    Trait(ty::TraitPredicate<'tcx>),
-    Ty(Ty<'tcx>),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
-pub enum FromEnv<'tcx> {
-    Trait(ty::TraitPredicate<'tcx>),
-    Ty(Ty<'tcx>),
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
-pub enum DomainGoal<'tcx> {
-    Holds(WhereClause<'tcx>),
-    WellFormed(WellFormed<'tcx>),
-    FromEnv(FromEnv<'tcx>),
-    Normalize(ty::ProjectionPredicate<'tcx>),
-}
-
-pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>;
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
-pub enum QuantifierKind {
-    Universal,
-    Existential,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
-pub enum GoalKind<'tcx> {
-    Implies(Clauses<'tcx>, Goal<'tcx>),
-    And(Goal<'tcx>, Goal<'tcx>),
-    Not(Goal<'tcx>),
-    DomainGoal(DomainGoal<'tcx>),
-    Quantified(QuantifierKind, ty::Binder<Goal<'tcx>>),
-    Subtype(Ty<'tcx>, Ty<'tcx>),
-    CannotProve,
-}
-
-pub type Goal<'tcx> = &'tcx GoalKind<'tcx>;
-
-pub type Goals<'tcx> = &'tcx List<Goal<'tcx>>;
-
-impl<'tcx> DomainGoal<'tcx> {
-    pub fn into_goal(self) -> GoalKind<'tcx> {
-        GoalKind::DomainGoal(self)
-    }
-
-    pub fn into_program_clause(self) -> ProgramClause<'tcx> {
-        ProgramClause {
-            goal: self,
-            hypotheses: ty::List::empty(),
-            category: ProgramClauseCategory::Other,
-        }
-    }
-}
-
-impl<'tcx> GoalKind<'tcx> {
-    pub fn from_poly_domain_goal(
-        domain_goal: PolyDomainGoal<'tcx>,
-        tcx: TyCtxt<'tcx>,
-    ) -> GoalKind<'tcx> {
-        match domain_goal.no_bound_vars() {
-            Some(p) => p.into_goal(),
-            None => GoalKind::Quantified(
-                QuantifierKind::Universal,
-                domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal())),
-            ),
-        }
-    }
-}
-
-/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
-/// Harrop Formulas".
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
-pub enum Clause<'tcx> {
-    Implies(ProgramClause<'tcx>),
-    ForAll(ty::Binder<ProgramClause<'tcx>>),
-}
-
-impl Clause<'tcx> {
-    pub fn category(self) -> ProgramClauseCategory {
-        match self {
-            Clause::Implies(clause) => clause.category,
-            Clause::ForAll(clause) => clause.skip_binder().category,
-        }
-    }
-}
-
-/// Multiple clauses.
-pub type Clauses<'tcx> = &'tcx List<Clause<'tcx>>;
-
-/// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
-/// that the domain goal `D` is true if `G1...Gn` are provable. This
-/// is equivalent to the implication `G1..Gn => D`; we usually write
-/// it with the reverse implication operator `:-` to emphasize the way
-/// that programs are actually solved (via backchaining, which starts
-/// with the goal to solve and proceeds from there).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
-pub struct ProgramClause<'tcx> {
-    /// This goal will be considered true ...
-    pub goal: DomainGoal<'tcx>,
-
-    /// ... if we can prove these hypotheses (there may be no hypotheses at all):
-    pub hypotheses: Goals<'tcx>,
-
-    /// Useful for filtering clauses.
-    pub category: ProgramClauseCategory,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
-pub enum ProgramClauseCategory {
-    ImpliedBound,
-    WellFormed,
-    Other,
-}
-
-/// A set of clauses that we assume to be true.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
-pub struct Environment<'tcx> {
-    pub clauses: Clauses<'tcx>,
-}
-
-impl Environment<'tcx> {
-    pub fn with<G>(self, goal: G) -> InEnvironment<'tcx, G> {
-        InEnvironment { environment: self, goal }
-    }
-}
-
-/// Something (usually a goal), along with an environment.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
-pub struct InEnvironment<'tcx, G> {
-    pub environment: Environment<'tcx>,
-    pub goal: G,
-}
-
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 
-#[derive(Clone, Debug, TypeFoldable)]
-pub enum SelectionError<'tcx> {
-    Unimplemented,
-    OutputTypeParameterMismatch(
-        ty::PolyTraitRef<'tcx>,
-        ty::PolyTraitRef<'tcx>,
-        ty::error::TypeError<'tcx>,
-    ),
-    TraitNotObjectSafe(DefId),
-    ConstEvalFailure(ErrorHandled),
-    Overflow,
-}
-
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
@@ -542,164 +151,6 @@ pub enum FulfillmentErrorCode<'tcx> {
     CodeAmbiguity,
 }
 
-/// When performing resolution, it is typically the case that there
-/// can be one of three outcomes:
-///
-/// - `Ok(Some(r))`: success occurred with result `r`
-/// - `Ok(None)`: could not definitely determine anything, usually due
-///   to inconclusive type inference.
-/// - `Err(e)`: error `e` occurred
-pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
-
-/// Given the successful resolution of an obligation, the `Vtable`
-/// indicates where the vtable comes from. Note that while we call this
-/// a "vtable", it does not necessarily indicate dynamic dispatch at
-/// runtime. `Vtable` instances just tell the compiler where to find
-/// methods, but in generic code those methods are typically statically
-/// dispatched -- only when an object is constructed is a `Vtable`
-/// instance reified into an actual vtable.
-///
-/// For example, the vtable may be tied to a specific impl (case A),
-/// or it may be relative to some bound that is in scope (case B).
-///
-/// ```
-/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
-/// impl<T:Clone> Clone<T> for Box<T> { ... }    // Impl_2
-/// impl Clone for int { ... }             // Impl_3
-///
-/// fn foo<T:Clone>(concrete: Option<Box<int>>,
-///                 param: T,
-///                 mixed: Option<T>) {
-///
-///    // Case A: Vtable points at a specific impl. Only possible when
-///    // type is concretely known. If the impl itself has bounded
-///    // type parameters, Vtable will carry resolutions for those as well:
-///    concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
-///
-///    // Case B: Vtable must be provided by caller. This applies when
-///    // type is a type parameter.
-///    param.clone();    // VtableParam
-///
-///    // Case C: A mix of cases A and B.
-///    mixed.clone();    // Vtable(Impl_1, [VtableParam])
-/// }
-/// ```
-///
-/// ### The type parameter `N`
-///
-/// See explanation on `VtableImplData`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub enum Vtable<'tcx, N> {
-    /// Vtable identifying a particular impl.
-    VtableImpl(VtableImplData<'tcx, N>),
-
-    /// Vtable for auto trait implementations.
-    /// This carries the information and nested obligations with regards
-    /// to an auto implementation for a trait `Trait`. The nested obligations
-    /// ensure the trait implementation holds for all the constituent types.
-    VtableAutoImpl(VtableAutoImplData<N>),
-
-    /// Successful resolution to an obligation provided by the caller
-    /// for some type parameter. The `Vec<N>` represents the
-    /// obligations incurred from normalizing the where-clause (if
-    /// any).
-    VtableParam(Vec<N>),
-
-    /// Virtual calls through an object.
-    VtableObject(VtableObjectData<'tcx, N>),
-
-    /// Successful resolution for a builtin trait.
-    VtableBuiltin(VtableBuiltinData<N>),
-
-    /// Vtable automatically generated for a closure. The `DefId` is the ID
-    /// of the closure expression. This is a `VtableImpl` in spirit, but the
-    /// impl is generated by the compiler and does not appear in the source.
-    VtableClosure(VtableClosureData<'tcx, N>),
-
-    /// Same as above, but for a function pointer type with the given signature.
-    VtableFnPointer(VtableFnPointerData<'tcx, N>),
-
-    /// Vtable automatically generated for a generator.
-    VtableGenerator(VtableGeneratorData<'tcx, N>),
-
-    /// Vtable for a trait alias.
-    VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
-}
-
-/// Identifies a particular impl in the source, along with a set of
-/// substitutions from the impl's type/lifetime parameters. The
-/// `nested` vector corresponds to the nested obligations attached to
-/// the impl's type parameters.
-///
-/// The type parameter `N` indicates the type used for "nested
-/// obligations" that are required by the impl. During type-check, this
-/// is `Obligation`, as one might expect. During codegen, however, this
-/// is `()`, because codegen only requires a shallow resolution of an
-/// impl, and nested obligations are satisfied later.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableImplData<'tcx, N> {
-    pub impl_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableGeneratorData<'tcx, N> {
-    pub generator_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    /// Nested obligations. This can be non-empty if the generator
-    /// signature contains associated types.
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableClosureData<'tcx, N> {
-    pub closure_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    /// Nested obligations. This can be non-empty if the closure
-    /// signature contains associated types.
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableAutoImplData<N> {
-    pub trait_def_id: DefId,
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableBuiltinData<N> {
-    pub nested: Vec<N>,
-}
-
-/// A vtable for some object-safe trait `Foo` automatically derived
-/// for the object type `Foo`.
-#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableObjectData<'tcx, N> {
-    /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
-    pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
-
-    /// The vtable is formed by concatenating together the method lists of
-    /// the base object trait and all supertraits; this is the start of
-    /// `upcast_trait_ref`'s methods in that vtable.
-    pub vtable_base: usize,
-
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableFnPointerData<'tcx, N> {
-    pub fn_ty: Ty<'tcx>,
-    pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct VtableTraitAliasData<'tcx, N> {
-    pub alias_def_id: DefId,
-    pub substs: SubstsRef<'tcx>,
-    pub nested: Vec<N>,
-}
-
 /// Creates predicate obligations from the generic bounds.
 pub fn predicates_for_generics<'tcx>(
     cause: ObligationCause<'tcx>,
@@ -1148,97 +599,6 @@ impl<'tcx, O> Obligation<'tcx, O> {
     }
 }
 
-impl<'tcx> ObligationCause<'tcx> {
-    #[inline]
-    pub fn new(
-        span: Span,
-        body_id: hir::HirId,
-        code: ObligationCauseCode<'tcx>,
-    ) -> ObligationCause<'tcx> {
-        ObligationCause { span, body_id, code }
-    }
-
-    pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
-        ObligationCause { span, body_id, code: MiscObligation }
-    }
-
-    pub fn dummy() -> ObligationCause<'tcx> {
-        ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }
-    }
-}
-
-impl ObligationCauseCode<'_> {
-    // Return the base obligation, ignoring derived obligations.
-    pub fn peel_derives(&self) -> &Self {
-        let mut base_cause = self;
-        while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
-            base_cause = &cause.parent_code;
-        }
-        base_cause
-    }
-}
-
-impl<'tcx, N> Vtable<'tcx, N> {
-    pub fn nested_obligations(self) -> Vec<N> {
-        match self {
-            VtableImpl(i) => i.nested,
-            VtableParam(n) => n,
-            VtableBuiltin(i) => i.nested,
-            VtableAutoImpl(d) => d.nested,
-            VtableClosure(c) => c.nested,
-            VtableGenerator(c) => c.nested,
-            VtableObject(d) => d.nested,
-            VtableFnPointer(d) => d.nested,
-            VtableTraitAlias(d) => d.nested,
-        }
-    }
-
-    pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M>
-    where
-        F: FnMut(N) -> M,
-    {
-        match self {
-            VtableImpl(i) => VtableImpl(VtableImplData {
-                impl_def_id: i.impl_def_id,
-                substs: i.substs,
-                nested: i.nested.into_iter().map(f).collect(),
-            }),
-            VtableParam(n) => VtableParam(n.into_iter().map(f).collect()),
-            VtableBuiltin(i) => {
-                VtableBuiltin(VtableBuiltinData { nested: i.nested.into_iter().map(f).collect() })
-            }
-            VtableObject(o) => VtableObject(VtableObjectData {
-                upcast_trait_ref: o.upcast_trait_ref,
-                vtable_base: o.vtable_base,
-                nested: o.nested.into_iter().map(f).collect(),
-            }),
-            VtableAutoImpl(d) => VtableAutoImpl(VtableAutoImplData {
-                trait_def_id: d.trait_def_id,
-                nested: d.nested.into_iter().map(f).collect(),
-            }),
-            VtableClosure(c) => VtableClosure(VtableClosureData {
-                closure_def_id: c.closure_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            }),
-            VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
-                generator_def_id: c.generator_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            }),
-            VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
-                fn_ty: p.fn_ty,
-                nested: p.nested.into_iter().map(f).collect(),
-            }),
-            VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
-                alias_def_id: d.alias_def_id,
-                substs: d.substs,
-                nested: d.nested.into_iter().map(f).collect(),
-            }),
-        }
-    }
-}
-
 impl<'tcx> FulfillmentError<'tcx> {
     fn new(
         obligation: PredicateObligation<'tcx>,
@@ -1266,42 +626,3 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         ..*providers
     };
 }
-
-pub trait ExClauseFold<'tcx>
-where
-    Self: chalk_engine::context::Context + Clone,
-{
-    fn fold_ex_clause_with<F: TypeFolder<'tcx>>(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        folder: &mut F,
-    ) -> chalk_engine::ExClause<Self>;
-
-    fn visit_ex_clause_with<V: TypeVisitor<'tcx>>(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        visitor: &mut V,
-    ) -> bool;
-}
-
-pub trait ChalkContextLift<'tcx>
-where
-    Self: chalk_engine::context::Context + Clone,
-{
-    type LiftedExClause: Debug + 'tcx;
-    type LiftedDelayedLiteral: Debug + 'tcx;
-    type LiftedLiteral: Debug + 'tcx;
-
-    fn lift_ex_clause_to_tcx(
-        ex_clause: &chalk_engine::ExClause<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedExClause>;
-
-    fn lift_delayed_literal_to_tcx(
-        ex_clause: &chalk_engine::DelayedLiteral<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedDelayedLiteral>;
-
-    fn lift_literal_to_tcx(
-        ex_clause: &chalk_engine::Literal<Self>,
-        tcx: TyCtxt<'tcx>,
-    ) -> Option<Self::LiftedLiteral>;
-}
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 3085837335a..fffcf66075f 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -19,52 +19,11 @@ use crate::ty::subst::{InternalSubsts, Subst};
 use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use rustc_hir::def_id::DefId;
-use rustc_macros::HashStable;
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
 use syntax::ast::Ident;
 
-/// Depending on the stage of compilation, we want projection to be
-/// more or less conservative.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
-pub enum Reveal {
-    /// At type-checking time, we refuse to project any associated
-    /// type that is marked `default`. Non-`default` ("final") types
-    /// are always projected. This is necessary in general for
-    /// soundness of specialization. However, we *could* allow
-    /// projections in fully-monomorphic cases. We choose not to,
-    /// because we prefer for `default type` to force the type
-    /// definition to be treated abstractly by any consumers of the
-    /// impl. Concretely, that means that the following example will
-    /// fail to compile:
-    ///
-    /// ```
-    /// trait Assoc {
-    ///     type Output;
-    /// }
-    ///
-    /// impl<T> Assoc for T {
-    ///     default type Output = bool;
-    /// }
-    ///
-    /// fn main() {
-    ///     let <() as Assoc>::Output = true;
-    /// }
-    UserFacing,
-
-    /// At codegen time, all monomorphic projections will succeed.
-    /// Also, `impl Trait` is normalized to the concrete type,
-    /// which has to be already collected by type-checking.
-    ///
-    /// NOTE: as `impl Trait`'s concrete type should *never*
-    /// be observable directly by the user, `Reveal::All`
-    /// should not be used by checks which may expose
-    /// type equality or type contents to the user.
-    /// There are some exceptions, e.g., around OIBITS and
-    /// transmute-checking, which expose some details, but
-    /// not the whole concrete type of the `impl Trait`.
-    All,
-}
+pub use rustc::traits::Reveal;
 
 pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
 
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 2e5ef5adcd3..a1d7a2836e4 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -1,10 +1,11 @@
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferOk;
-use crate::ty::subst::GenericArg;
-use crate::ty::{self, Ty, TyCtxt};
-use rustc_span::source_map::Span;
-use std::iter::FromIterator;
+
+use rustc::ty::subst::GenericArg;
+use rustc::ty::{self, Ty, TyCtxt};
+
+pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
 
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
@@ -65,76 +66,6 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     }
 }
 
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
-pub struct DropckOutlivesResult<'tcx> {
-    pub kinds: Vec<GenericArg<'tcx>>,
-    pub overflows: Vec<Ty<'tcx>>,
-}
-
-impl<'tcx> DropckOutlivesResult<'tcx> {
-    pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
-        if let Some(overflow_ty) = self.overflows.iter().next() {
-            rustc_errors::struct_span_err!(
-                tcx.sess,
-                span,
-                E0320,
-                "overflow while adding drop-check rules for {}",
-                ty,
-            )
-            .note(&format!("overflowed on {}", overflow_ty))
-            .emit();
-        }
-    }
-
-    pub fn into_kinds_reporting_overflows(
-        self,
-        tcx: TyCtxt<'tcx>,
-        span: Span,
-        ty: Ty<'tcx>,
-    ) -> Vec<GenericArg<'tcx>> {
-        self.report_overflows(tcx, span, ty);
-        let DropckOutlivesResult { kinds, overflows: _ } = self;
-        kinds
-    }
-}
-
-/// A set of constraints that need to be satisfied in order for
-/// a type to be valid for destruction.
-#[derive(Clone, Debug, HashStable)]
-pub struct DtorckConstraint<'tcx> {
-    /// Types that are required to be alive in order for this
-    /// type to be valid for destruction.
-    pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
-
-    /// Types that could not be resolved: projections and params.
-    pub dtorck_types: Vec<Ty<'tcx>>,
-
-    /// If, during the computation of the dtorck constraint, we
-    /// overflow, that gets recorded here. The caller is expected to
-    /// report an error.
-    pub overflows: Vec<Ty<'tcx>>,
-}
-
-impl<'tcx> DtorckConstraint<'tcx> {
-    pub fn empty() -> DtorckConstraint<'tcx> {
-        DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
-    }
-}
-
-impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
-    fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
-        let mut result = Self::empty();
-
-        for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
-            result.outlives.extend(outlives);
-            result.dtorck_types.extend(dtorck_types);
-            result.overflows.extend(overflows);
-        }
-
-        result
-    }
-}
-
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
 /// outlive. This is similar but not *quite* the same as the
diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc/traits/query/method_autoderef.rs
index 4ef775750ec..80748c5ef38 100644
--- a/src/librustc/traits/query/method_autoderef.rs
+++ b/src/librustc/traits/query/method_autoderef.rs
@@ -1,33 +1 @@
-use crate::infer::canonical::{Canonical, QueryResponse};
-use crate::ty::Ty;
-use rustc_data_structures::sync::Lrc;
-
-#[derive(Debug, HashStable)]
-pub struct CandidateStep<'tcx> {
-    pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
-    pub autoderefs: usize,
-    /// `true` if the type results from a dereference of a raw pointer.
-    /// when assembling candidates, we include these steps, but not when
-    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
-    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
-    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
-    pub from_unsafe_deref: bool,
-    pub unsize: bool,
-}
-
-#[derive(Clone, Debug, HashStable)]
-pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be find.
-    pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
-    /// If Some(T), a type autoderef reported an error on.
-    pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
-    /// If `true`, `steps` has been truncated due to reaching the
-    /// recursion limit.
-    pub reached_recursion_limit: bool,
-}
-
-#[derive(Debug, HashStable)]
-pub struct MethodAutoderefBadTy<'tcx> {
-    pub reached_raw_pointer: bool,
-    pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
-}
+pub use rustc::traits::query::{CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult};
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index 440268aab8f..20a873dc4c6 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -5,10 +5,6 @@
 //! The providers for the queries defined here can be found in
 //! `librustc_traits`.
 
-use crate::infer::canonical::Canonical;
-use crate::ty::error::TypeError;
-use crate::ty::{self, Ty};
-
 pub mod dropck_outlives;
 pub mod evaluate_obligation;
 pub mod method_autoderef;
@@ -16,35 +12,4 @@ pub mod normalize;
 pub mod outlives_bounds;
 pub mod type_op;
 
-pub type CanonicalProjectionGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
-
-pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
-
-pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
-
-pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;
-
-pub type CanonicalTypeOpEqGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;
-
-pub type CanonicalTypeOpSubtypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::subtype::Subtype<'tcx>>>;
-
-pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>;
-
-pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize<T>>>;
-
-#[derive(Clone, Debug, HashStable)]
-pub struct NoSolution;
-
-pub type Fallible<T> = Result<T, NoSolution>;
-
-impl<'tcx> From<TypeError<'tcx>> for NoSolution {
-    fn from(_: TypeError<'tcx>) -> NoSolution {
-        NoSolution
-    }
-}
+pub use rustc::traits::types::query::*;
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 20d7b556377..737b4fc6bb9 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -13,6 +13,8 @@ use crate::ty::{self, Ty, TyCtxt};
 
 use super::NoSolution;
 
+pub use rustc::traits::query::NormalizationResult;
+
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Normalize `value` in the context of the inference context,
     /// yielding a resulting type, or an error if `value` cannot be
@@ -59,13 +61,6 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     }
 }
 
-/// Result from the `normalize_projection_ty` query.
-#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct NormalizationResult<'tcx> {
-    /// Result of normalization.
-    pub normalized_ty: Ty<'tcx>,
-}
-
 struct QueryNormalizer<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     cause: &'cx ObligationCause<'tcx>,
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index 07e57e847b1..594faffa5f3 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -6,43 +6,7 @@ use crate::ty::{self, Ty};
 use rustc_hir as hir;
 use rustc_span::source_map::Span;
 
-use crate::ich::StableHashingContext;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use std::mem;
-
-/// Outlives bounds are relationships between generic parameters,
-/// whether they both be regions (`'a: 'b`) or whether types are
-/// involved (`T: 'a`). These relationships can be extracted from the
-/// full set of predicates we understand or also from types (in which
-/// case they are called implied bounds). They are fed to the
-/// `OutlivesEnv` which in turn is supplied to the region checker and
-/// other parts of the inference system.
-#[derive(Clone, Debug, TypeFoldable, Lift)]
-pub enum OutlivesBound<'tcx> {
-    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
-    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            OutlivesBound::RegionSubRegion(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            OutlivesBound::RegionSubParam(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            OutlivesBound::RegionSubProjection(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
+pub use rustc::traits::query::OutlivesBound;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs
index 46b656eb945..b14b79f0907 100644
--- a/src/librustc/traits/query/type_op/ascribe_user_type.rs
+++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs
@@ -1,21 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::subst::UserSubsts;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct AscribeUserType<'tcx> {
-    pub mir_ty: Ty<'tcx>,
-    pub def_id: DefId,
-    pub user_substs: UserSubsts<'tcx>,
-}
-
-impl<'tcx> AscribeUserType<'tcx> {
-    pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
-        Self { mir_ty, def_id, user_substs }
-    }
-}
+pub use rustc::traits::query::type_op::AscribeUserType;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     type QueryResponse = ();
diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs
index 267722362c5..1de13430d46 100644
--- a/src/librustc/traits/query/type_op/eq.rs
+++ b/src/librustc/traits/query/type_op/eq.rs
@@ -1,18 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Eq<'tcx> {
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
-
-impl<'tcx> Eq<'tcx> {
-    pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self {
-        Self { a, b }
-    }
-}
+pub use rustc::traits::query::type_op::Eq;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
     type QueryResponse = ();
diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs
index adf63e4d60c..2d03d77cf66 100644
--- a/src/librustc/traits/query/type_op/mod.rs
+++ b/src/librustc/traits/query/type_op/mod.rs
@@ -19,6 +19,8 @@ pub mod prove_predicate;
 use self::prove_predicate::ProvePredicate;
 pub mod subtype;
 
+pub use crate::traits::types::query::type_op::*;
+
 /// "Type ops" are used in NLL to perform some particular action and
 /// extract out the resulting region constraints (or an error if it
 /// cannot be completed).
diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs
index 8a028eecd5b..b1e0e29620d 100644
--- a/src/librustc/traits/query/type_op/normalize.rs
+++ b/src/librustc/traits/query/type_op/normalize.rs
@@ -4,19 +4,7 @@ use crate::ty::fold::TypeFoldable;
 use crate::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
 use std::fmt;
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Normalize<T> {
-    pub value: T,
-}
-
-impl<'tcx, T> Normalize<T>
-where
-    T: fmt::Debug + TypeFoldable<'tcx>,
-{
-    pub fn new(value: T) -> Self {
-        Self { value }
-    }
-}
+pub use rustc::traits::query::type_op::Normalize;
 
 impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
 where
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs
index 15870ec95d8..92cfb82e27e 100644
--- a/src/librustc/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc/traits/query/type_op/prove_predicate.rs
@@ -2,16 +2,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Predicate, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct ProvePredicate<'tcx> {
-    pub predicate: Predicate<'tcx>,
-}
-
-impl<'tcx> ProvePredicate<'tcx> {
-    pub fn new(predicate: Predicate<'tcx>) -> Self {
-        ProvePredicate { predicate }
-    }
-}
+pub use rustc::traits::query::type_op::ProvePredicate;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     type QueryResponse = ();
diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs
index c70508a20a1..2877a74aaff 100644
--- a/src/librustc/traits/query/type_op/subtype.rs
+++ b/src/librustc/traits/query/type_op/subtype.rs
@@ -1,18 +1,8 @@
 use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
-use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{ParamEnvAnd, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
-pub struct Subtype<'tcx> {
-    pub sub: Ty<'tcx>,
-    pub sup: Ty<'tcx>,
-}
-
-impl<'tcx> Subtype<'tcx> {
-    pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self {
-        Self { sub, sup }
-    }
-}
+pub use rustc::traits::query::type_op::Subtype;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
     type QueryResponse = ();
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index ba0a270638c..e4ef68c167f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -41,7 +41,6 @@ use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, Wit
 use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::Lock;
 use rustc_hir as hir;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::symbol::sym;
@@ -53,6 +52,8 @@ use std::iter;
 use std::rc::Rc;
 use syntax::{ast, attr};
 
+pub use rustc::traits::types::select::*;
+
 pub struct SelectionContext<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
 
@@ -181,146 +182,6 @@ struct TraitObligationStack<'prev, 'tcx> {
     dfn: usize,
 }
 
-#[derive(Clone, Default)]
-pub struct SelectionCache<'tcx> {
-    hashmap: Lock<
-        FxHashMap<
-            ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
-            WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
-        >,
-    >,
-}
-
-/// The selection process begins by considering all impls, where
-/// clauses, and so forth that might resolve an obligation. Sometimes
-/// we'll be able to say definitively that (e.g.) an impl does not
-/// apply to the obligation: perhaps it is defined for `usize` but the
-/// obligation is for `int`. In that case, we drop the impl out of the
-/// list. But the other cases are considered *candidates*.
-///
-/// For selection to succeed, there must be exactly one matching
-/// candidate. If the obligation is fully known, this is guaranteed
-/// by coherence. However, if the obligation contains type parameters
-/// or variables, there may be multiple such impls.
-///
-/// It is not a real problem if multiple matching impls exist because
-/// of type variables - it just means the obligation isn't sufficiently
-/// elaborated. In that case we report an ambiguity, and the caller can
-/// try again after more type information has been gathered or report a
-/// "type annotations needed" error.
-///
-/// However, with type parameters, this can be a real problem - type
-/// parameters don't unify with regular types, but they *can* unify
-/// with variables from blanket impls, and (unless we know its bounds
-/// will always be satisfied) picking the blanket impl will be wrong
-/// for at least *some* substitutions. To make this concrete, if we have
-///
-///    trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
-///    impl<T: fmt::Debug> AsDebug for T {
-///        type Out = T;
-///        fn debug(self) -> fmt::Debug { self }
-///    }
-///    fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
-///
-/// we can't just use the impl to resolve the `<T as AsDebug>` obligation
-/// -- a type from another crate (that doesn't implement `fmt::Debug`) could
-/// implement `AsDebug`.
-///
-/// Because where-clauses match the type exactly, multiple clauses can
-/// only match if there are unresolved variables, and we can mostly just
-/// report this ambiguity in that case. This is still a problem - we can't
-/// *do anything* with ambiguities that involve only regions. This is issue
-/// #21974.
-///
-/// If a single where-clause matches and there are no inference
-/// variables left, then it definitely matches and we can just select
-/// it.
-///
-/// In fact, we even select the where-clause when the obligation contains
-/// inference variables. The can lead to inference making "leaps of logic",
-/// for example in this situation:
-///
-///    pub trait Foo<T> { fn foo(&self) -> T; }
-///    impl<T> Foo<()> for T { fn foo(&self) { } }
-///    impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
-///
-///    pub fn foo<T>(t: T) where T: Foo<bool> {
-///       println!("{:?}", <T as Foo<_>>::foo(&t));
-///    }
-///    fn main() { foo(false); }
-///
-/// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
-/// impl and the where-clause. We select the where-clause and unify `$0=bool`,
-/// so the program prints "false". However, if the where-clause is omitted,
-/// the blanket impl is selected, we unify `$0=()`, and the program prints
-/// "()".
-///
-/// Exactly the same issues apply to projection and object candidates, except
-/// that we can have both a projection candidate and a where-clause candidate
-/// for the same obligation. In that case either would do (except that
-/// different "leaps of logic" would occur if inference variables are
-/// present), and we just pick the where-clause. This is, for example,
-/// required for associated types to work in default impls, as the bounds
-/// are visible both as projection bounds and as where-clauses from the
-/// parameter environment.
-#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
-enum SelectionCandidate<'tcx> {
-    BuiltinCandidate {
-        /// `false` if there are no *further* obligations.
-        has_nested: bool,
-    },
-    ParamCandidate(ty::PolyTraitRef<'tcx>),
-    ImplCandidate(DefId),
-    AutoImplCandidate(DefId),
-
-    /// This is a trait matching with a projected type as `Self`, and
-    /// we found an applicable bound in the trait definition.
-    ProjectionCandidate,
-
-    /// Implementation of a `Fn`-family trait by one of the anonymous types
-    /// generated for a `||` expression.
-    ClosureCandidate,
-
-    /// Implementation of a `Generator` trait by one of the anonymous types
-    /// generated for a generator.
-    GeneratorCandidate,
-
-    /// Implementation of a `Fn`-family trait by one of the anonymous
-    /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
-    FnPointerCandidate,
-
-    TraitAliasCandidate(DefId),
-
-    ObjectCandidate,
-
-    BuiltinObjectCandidate,
-
-    BuiltinUnsizeCandidate,
-}
-
-impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
-    type Lifted = SelectionCandidate<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        Some(match *self {
-            BuiltinCandidate { has_nested } => BuiltinCandidate { has_nested },
-            ImplCandidate(def_id) => ImplCandidate(def_id),
-            AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
-            ProjectionCandidate => ProjectionCandidate,
-            ClosureCandidate => ClosureCandidate,
-            GeneratorCandidate => GeneratorCandidate,
-            FnPointerCandidate => FnPointerCandidate,
-            TraitAliasCandidate(def_id) => TraitAliasCandidate(def_id),
-            ObjectCandidate => ObjectCandidate,
-            BuiltinObjectCandidate => BuiltinObjectCandidate,
-            BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
-
-            ParamCandidate(ref trait_ref) => {
-                return tcx.lift(trait_ref).map(ParamCandidate);
-            }
-        })
-    }
-}
-
 struct SelectionCandidateSet<'tcx> {
     // A list of candidates that definitely apply to the current
     // obligation (meaning: types unify).
@@ -350,134 +211,6 @@ enum BuiltinImplConditions<'tcx> {
     Ambiguous,
 }
 
-/// The result of trait evaluation. The order is important
-/// here as the evaluation of a list is the maximum of the
-/// evaluations.
-///
-/// The evaluation results are ordered:
-///     - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
-///       implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
-///     - `EvaluatedToErr` implies `EvaluatedToRecur`
-///     - the "union" of evaluation results is equal to their maximum -
-///     all the "potential success" candidates can potentially succeed,
-///     so they are noops when unioned with a definite error, and within
-///     the categories it's easy to see that the unions are correct.
-#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
-pub enum EvaluationResult {
-    /// Evaluation successful.
-    EvaluatedToOk,
-    /// Evaluation successful, but there were unevaluated region obligations.
-    EvaluatedToOkModuloRegions,
-    /// Evaluation is known to be ambiguous -- it *might* hold for some
-    /// assignment of inference variables, but it might not.
-    ///
-    /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
-    /// know whether this obligation holds or not -- it is the result we
-    /// would get with an empty stack, and therefore is cacheable.
-    EvaluatedToAmbig,
-    /// Evaluation failed because of recursion involving inference
-    /// variables. We are somewhat imprecise there, so we don't actually
-    /// know the real result.
-    ///
-    /// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
-    EvaluatedToUnknown,
-    /// Evaluation failed because we encountered an obligation we are already
-    /// trying to prove on this branch.
-    ///
-    /// We know this branch can't be a part of a minimal proof-tree for
-    /// the "root" of our cycle, because then we could cut out the recursion
-    /// and maintain a valid proof tree. However, this does not mean
-    /// that all the obligations on this branch do not hold -- it's possible
-    /// that we entered this branch "speculatively", and that there
-    /// might be some other way to prove this obligation that does not
-    /// go through this cycle -- so we can't cache this as a failure.
-    ///
-    /// For example, suppose we have this:
-    ///
-    /// ```rust,ignore (pseudo-Rust)
-    /// pub trait Trait { fn xyz(); }
-    /// // This impl is "useless", but we can still have
-    /// // an `impl Trait for SomeUnsizedType` somewhere.
-    /// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
-    ///
-    /// pub fn foo<T: Trait + ?Sized>() {
-    ///     <T as Trait>::xyz();
-    /// }
-    /// ```
-    ///
-    /// When checking `foo`, we have to prove `T: Trait`. This basically
-    /// translates into this:
-    ///
-    /// ```plain,ignore
-    /// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
-    /// ```
-    ///
-    /// When we try to prove it, we first go the first option, which
-    /// recurses. This shows us that the impl is "useless" -- it won't
-    /// tell us that `T: Trait` unless it already implemented `Trait`
-    /// by some other means. However, that does not prevent `T: Trait`
-    /// does not hold, because of the bound (which can indeed be satisfied
-    /// by `SomeUnsizedType` from another crate).
-    //
-    // FIXME: when an `EvaluatedToRecur` goes past its parent root, we
-    // ought to convert it to an `EvaluatedToErr`, because we know
-    // there definitely isn't a proof tree for that obligation. Not
-    // doing so is still sound -- there isn't any proof tree, so the
-    // branch still can't be a part of a minimal one -- but does not re-enable caching.
-    EvaluatedToRecur,
-    /// Evaluation failed.
-    EvaluatedToErr,
-}
-
-impl EvaluationResult {
-    /// Returns `true` if this evaluation result is known to apply, even
-    /// considering outlives constraints.
-    pub fn must_apply_considering_regions(self) -> bool {
-        self == EvaluatedToOk
-    }
-
-    /// Returns `true` if this evaluation result is known to apply, ignoring
-    /// outlives constraints.
-    pub fn must_apply_modulo_regions(self) -> bool {
-        self <= EvaluatedToOkModuloRegions
-    }
-
-    pub fn may_apply(self) -> bool {
-        match self {
-            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
-                true
-            }
-
-            EvaluatedToErr | EvaluatedToRecur => false,
-        }
-    }
-
-    fn is_stack_dependent(self) -> bool {
-        match self {
-            EvaluatedToUnknown | EvaluatedToRecur => true,
-
-            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
-        }
-    }
-}
-
-/// Indicates that trait evaluation caused overflow.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
-pub struct OverflowError;
-
-impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
-    fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
-        SelectionError::Overflow
-    }
-}
-
-#[derive(Clone, Default)]
-pub struct EvaluationCache<'tcx> {
-    hashmap: Lock<
-        FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
-    >,
-}
-
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
@@ -3827,20 +3560,6 @@ impl<'tcx> TraitObligation<'tcx> {
     }
 }
 
-impl<'tcx> SelectionCache<'tcx> {
-    /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
-    pub fn clear(&self) {
-        *self.hashmap.borrow_mut() = Default::default();
-    }
-}
-
-impl<'tcx> EvaluationCache<'tcx> {
-    /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
-    pub fn clear(&self) {
-        *self.hashmap.borrow_mut() = Default::default();
-    }
-}
-
 impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
     fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
         TraitObligationStackList::with(self)
@@ -4126,20 +3845,3 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
         write!(f, "TraitObligationStack({:?})", self.obligation)
     }
 }
-
-#[derive(Clone, Eq, PartialEq)]
-pub struct WithDepNode<T> {
-    dep_node: DepNodeIndex,
-    cached_value: T,
-}
-
-impl<T: Clone> WithDepNode<T> {
-    pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
-        WithDepNode { dep_node, cached_value }
-    }
-
-    pub fn get(&self, tcx: TyCtxt<'_>) -> T {
-        tcx.dep_graph.read_index(self.dep_node);
-        self.cached_value.clone()
-    }
-}
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 9509b6220eb..c90fa428001 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -1,58 +1,11 @@
 use super::OverlapError;
 
-use crate::ich::{self, StableHashingContext};
 use crate::traits;
-use crate::ty::fast_reject::{self, SimplifiedType};
-use crate::ty::{self, TyCtxt, TypeFoldable};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::{DefId, DefIdMap};
-use syntax::ast::Ident;
-
-/// A per-trait graph of impls in specialization order. At the moment, this
-/// graph forms a tree rooted with the trait itself, with all other nodes
-/// representing impls, and parent-child relationships representing
-/// specializations.
-///
-/// The graph provides two key services:
-///
-/// - Construction. This implicitly checks for overlapping impls (i.e., impls
-///   that overlap but where neither specializes the other -- an artifact of the
-///   simple "chain" rule.
-///
-/// - Parent extraction. In particular, the graph can give you the *immediate*
-///   parents of a given specializing impl, which is needed for extracting
-///   default items amongst other things. In the simple "chain" rule, every impl
-///   has at most one parent.
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
-pub struct Graph {
-    // All impls have a parent; the "root" impls have as their parent the `def_id`
-    // of the trait.
-    parent: DefIdMap<DefId>,
-
-    // The "root" impls are found by looking up the trait's def_id.
-    children: DefIdMap<Children>,
-}
+use rustc::ty::fast_reject::{self, SimplifiedType};
+use rustc::ty::{self, TyCtxt, TypeFoldable};
+use rustc_hir::def_id::DefId;
 
-/// Children of a given impl, grouped into blanket/non-blanket varieties as is
-/// done in `TraitDef`.
-#[derive(Default, RustcEncodable, RustcDecodable)]
-struct Children {
-    // Impls of a trait (or specializations of a given impl). To allow for
-    // quicker lookup, the impls are indexed by a simplified version of their
-    // `Self` type: impls with a simplifiable `Self` are stored in
-    // `nonblanket_impls` keyed by it, while all other impls are stored in
-    // `blanket_impls`.
-    //
-    // A similar division is used within `TraitDef`, but the lists there collect
-    // together *all* the impls for a trait, and are populated prior to building
-    // the specialization graph.
-    /// Impls of the trait.
-    nonblanket_impls: FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>,
-
-    /// Blanket impls associated with the trait.
-    blanket_impls: Vec<DefId>,
-}
+pub use rustc::traits::types::specialization_graph::*;
 
 #[derive(Copy, Clone, Debug)]
 pub enum FutureCompatOverlapErrorKind {
@@ -269,10 +222,6 @@ where
 }
 
 impl<'tcx> Graph {
-    pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default() }
-    }
-
     /// Insert a local impl into the specialization graph. If an existing impl
     /// conflicts with it (has overlap, but neither specializes the other),
     /// information about the area of overlap is returned in the `Err`.
@@ -383,145 +332,4 @@ impl<'tcx> Graph {
 
         self.children.entry(parent).or_default().insert_blindly(tcx, child);
     }
-
-    /// The parent of a given impl, which is the `DefId` of the trait when the
-    /// impl is a "specialization root".
-    pub fn parent(&self, child: DefId) -> DefId {
-        *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {:?}", child))
-    }
-}
-
-/// A node in the specialization graph is either an impl or a trait
-/// definition; either can serve as a source of item definitions.
-/// There is always exactly one trait definition node: the root.
-#[derive(Debug, Copy, Clone)]
-pub enum Node {
-    Impl(DefId),
-    Trait(DefId),
-}
-
-impl<'tcx> Node {
-    pub fn is_from_trait(&self) -> bool {
-        match *self {
-            Node::Trait(..) => true,
-            _ => false,
-        }
-    }
-
-    /// Iterate over the items defined directly by the given (impl or trait) node.
-    pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> {
-        tcx.associated_items(self.def_id())
-    }
-
-    /// Finds an associated item defined in this node.
-    ///
-    /// If this returns `None`, the item can potentially still be found in
-    /// parents of this node.
-    pub fn item(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_item_name: Ident,
-        trait_item_kind: ty::AssocKind,
-        trait_def_id: DefId,
-    ) -> Option<ty::AssocItem> {
-        use crate::ty::AssocKind::*;
-
-        tcx.associated_items(self.def_id()).find(move |impl_item| {
-            match (trait_item_kind, impl_item.kind) {
-                | (Const, Const)
-                | (Method, Method)
-                | (Type, Type)
-                | (Type, OpaqueTy)  // assoc. types can be made opaque in impls
-                => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id),
-
-                | (Const, _)
-                | (Method, _)
-                | (Type, _)
-                | (OpaqueTy, _)
-                => false,
-            }
-        })
-    }
-
-    pub fn def_id(&self) -> DefId {
-        match *self {
-            Node::Impl(did) => did,
-            Node::Trait(did) => did,
-        }
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct Ancestors<'tcx> {
-    trait_def_id: DefId,
-    specialization_graph: &'tcx Graph,
-    current_source: Option<Node>,
-}
-
-impl Iterator for Ancestors<'_> {
-    type Item = Node;
-    fn next(&mut self) -> Option<Node> {
-        let cur = self.current_source.take();
-        if let Some(Node::Impl(cur_impl)) = cur {
-            let parent = self.specialization_graph.parent(cur_impl);
-
-            self.current_source = if parent == self.trait_def_id {
-                Some(Node::Trait(parent))
-            } else {
-                Some(Node::Impl(parent))
-            };
-        }
-        cur
-    }
-}
-
-pub struct NodeItem<T> {
-    pub node: Node,
-    pub item: T,
-}
-
-impl<T> NodeItem<T> {
-    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
-        NodeItem { node: self.node, item: f(self.item) }
-    }
-}
-
-impl<'tcx> Ancestors<'tcx> {
-    /// Finds the bottom-most (ie. most specialized) definition of an associated
-    /// item.
-    pub fn leaf_def(
-        mut self,
-        tcx: TyCtxt<'tcx>,
-        trait_item_name: Ident,
-        trait_item_kind: ty::AssocKind,
-    ) -> Option<NodeItem<ty::AssocItem>> {
-        let trait_def_id = self.trait_def_id;
-        self.find_map(|node| {
-            node.item(tcx, trait_item_name, trait_item_kind, trait_def_id)
-                .map(|item| NodeItem { node, item })
-        })
-    }
-}
-
-/// Walk up the specialization ancestors of a given impl, starting with that
-/// impl itself.
-pub fn ancestors(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    start_from_impl: DefId,
-) -> Ancestors<'tcx> {
-    let specialization_graph = tcx.specialization_graph_of(trait_def_id);
-    Ancestors {
-        trait_def_id,
-        specialization_graph,
-        current_source: Some(Node::Impl(start_from_impl)),
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Children {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let Children { ref nonblanket_impls, ref blanket_impls } = *self;
-
-        ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls);
-    }
 }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 58204a460d7..80731c7b189 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -1,14 +1,9 @@
 use crate::traits;
 use crate::traits::project::Normalized;
+use crate::ty;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::{self, Lift, Ty, TyCtxt};
-use chalk_engine;
-use rustc_span::symbol::Symbol;
-use smallvec::SmallVec;
 
-use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
-use std::rc::Rc;
 
 // Structural impls for the structs in `traits`.
 
@@ -32,102 +27,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> {
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            super::VtableImpl(ref v) => write!(f, "{:?}", v),
-
-            super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
-
-            super::VtableClosure(ref d) => write!(f, "{:?}", d),
-
-            super::VtableGenerator(ref d) => write!(f, "{:?}", d),
-
-            super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
-
-            super::VtableObject(ref d) => write!(f, "{:?}", d),
-
-            super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
-
-            super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
-
-            super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
-        }
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
-            self.impl_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
-            self.generator_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
-            self.closure_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "VtableBuiltinData(nested={:?})", self.nested)
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
-            self.trait_def_id, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
-            self.upcast_trait_ref, self.vtable_base, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
-            self.alias_def_id, self.substs, self.nested
-        )
-    }
-}
-
 impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
@@ -153,531 +52,6 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::WhereClause::*;
-
-        // Bypass `ty::print` because it does not print out anonymous regions.
-        // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
-        fn write_region_name<'tcx>(
-            r: ty::Region<'tcx>,
-            fmt: &mut fmt::Formatter<'_>,
-        ) -> fmt::Result {
-            match r {
-                ty::ReLateBound(index, br) => match br {
-                    ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
-                    ty::BoundRegion::BrAnon(var) => {
-                        if *index == ty::INNERMOST {
-                            write!(fmt, "'^{}", var)
-                        } else {
-                            write!(fmt, "'^{}_{}", index.index(), var)
-                        }
-                    }
-                    _ => write!(fmt, "'_"),
-                },
-
-                _ => write!(fmt, "{}", r),
-            }
-        }
-
-        match self {
-            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
-            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
-            RegionOutlives(predicate) => {
-                write!(fmt, "RegionOutlives({}: ", predicate.0)?;
-                write_region_name(predicate.1, fmt)?;
-                write!(fmt, ")")
-            }
-            TypeOutlives(predicate) => {
-                write!(fmt, "TypeOutlives({}: ", predicate.0)?;
-                write_region_name(predicate.1, fmt)?;
-                write!(fmt, ")")
-            }
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::WellFormed::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
-            Ty(ty) => write!(fmt, "WellFormed({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::FromEnv::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
-            Ty(ty) => write!(fmt, "FromEnv({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::DomainGoal::*;
-
-        match self {
-            Holds(wc) => write!(fmt, "{}", wc),
-            WellFormed(wf) => write!(fmt, "{}", wf),
-            FromEnv(from_env) => write!(fmt, "{}", from_env),
-            Normalize(projection) => {
-                write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
-            }
-        }
-    }
-}
-
-impl fmt::Display for traits::QuantifierKind {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::QuantifierKind::*;
-
-        match self {
-            Universal => write!(fmt, "forall"),
-            Existential => write!(fmt, "exists"),
-        }
-    }
-}
-
-/// Collect names for regions / types bound by a quantified goal / clause.
-/// This collector does not try to do anything clever like in `ty::print`, it's just used
-/// for debug output in tests anyway.
-struct BoundNamesCollector {
-    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
-    regions: BTreeSet<Symbol>,
-
-    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
-    // by the list of type parameters.
-    types: BTreeMap<u32, Symbol>,
-
-    binder_index: ty::DebruijnIndex,
-}
-
-impl BoundNamesCollector {
-    fn new() -> Self {
-        BoundNamesCollector {
-            regions: BTreeSet::new(),
-            types: BTreeMap::new(),
-            binder_index: ty::INNERMOST,
-        }
-    }
-
-    fn is_empty(&self) -> bool {
-        self.regions.is_empty() && self.types.is_empty()
-    }
-
-    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut start = true;
-        for r in &self.regions {
-            if !start {
-                write!(fmt, ", ")?;
-            }
-            start = false;
-            write!(fmt, "{}", r)?;
-        }
-        for (_, t) in &self.types {
-            if !start {
-                write!(fmt, ", ")?;
-            }
-            start = false;
-            write!(fmt, "{}", t)?;
-        }
-        Ok(())
-    }
-}
-
-impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
-    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-        match t.kind {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                self.types.insert(
-                    bound_ty.var.as_u32(),
-                    match bound_ty.kind {
-                        ty::BoundTyKind::Param(name) => name,
-                        ty::BoundTyKind::Anon => {
-                            Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
-                        }
-                    },
-                );
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        match r {
-            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
-                ty::BoundRegion::BrNamed(_, name) => {
-                    self.regions.insert(*name);
-                }
-
-                ty::BoundRegion::BrAnon(var) => {
-                    self.regions.insert(Symbol::intern(&format!("'^{}", var)));
-                }
-
-                _ => (),
-            },
-
-            _ => (),
-        };
-
-        r.super_visit_with(self)
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Goal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::GoalKind::*;
-
-        match self {
-            Implies(hypotheses, goal) => {
-                write!(fmt, "if (")?;
-                for (index, hyp) in hypotheses.iter().enumerate() {
-                    if index > 0 {
-                        write!(fmt, ", ")?;
-                    }
-                    write!(fmt, "{}", hyp)?;
-                }
-                write!(fmt, ") {{ {} }}", goal)
-            }
-            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
-            Not(goal) => write!(fmt, "not {{ {} }}", goal),
-            DomainGoal(goal) => write!(fmt, "{}", goal),
-            Quantified(qkind, goal) => {
-                let mut collector = BoundNamesCollector::new();
-                goal.skip_binder().visit_with(&mut collector);
-
-                if !collector.is_empty() {
-                    write!(fmt, "{}<", qkind)?;
-                    collector.write_names(fmt)?;
-                    write!(fmt, "> {{ ")?;
-                }
-
-                write!(fmt, "{}", goal.skip_binder())?;
-
-                if !collector.is_empty() {
-                    write!(fmt, " }}")?;
-                }
-
-                Ok(())
-            }
-            Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
-            CannotProve => write!(fmt, "CannotProve"),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let traits::ProgramClause { goal, hypotheses, .. } = self;
-        write!(fmt, "{}", goal)?;
-        if !hypotheses.is_empty() {
-            write!(fmt, " :- ")?;
-            for (index, condition) in hypotheses.iter().enumerate() {
-                if index > 0 {
-                    write!(fmt, ", ")?;
-                }
-                write!(fmt, "{}", condition)?;
-            }
-        }
-        write!(fmt, ".")
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Clause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::Clause::*;
-
-        match self {
-            Implies(clause) => write!(fmt, "{}", clause),
-            ForAll(clause) => {
-                let mut collector = BoundNamesCollector::new();
-                clause.skip_binder().visit_with(&mut collector);
-
-                if !collector.is_empty() {
-                    write!(fmt, "forall<")?;
-                    collector.write_names(fmt)?;
-                    write!(fmt, "> {{ ")?;
-                }
-
-                write!(fmt, "{}", clause.skip_binder())?;
-
-                if !collector.is_empty() {
-                    write!(fmt, " }}")?;
-                }
-
-                Ok(())
-            }
-        }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Lift implementations
-
-impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
-    type Lifted = traits::SelectionError<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            super::Unimplemented => Some(super::Unimplemented),
-            super::OutputTypeParameterMismatch(a, b, ref err) => {
-                tcx.lift(&(a, b)).and_then(|(a, b)| {
-                    tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
-                })
-            }
-            super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
-            super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
-            super::Overflow => Some(super::Overflow),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
-    type Lifted = traits::ObligationCauseCode<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            super::ReturnNoExpression => Some(super::ReturnNoExpression),
-            super::MiscObligation => Some(super::MiscObligation),
-            super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
-            super::TupleElem => Some(super::TupleElem),
-            super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
-            super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
-            super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
-            super::ReferenceOutlivesReferent(ty) => {
-                tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
-            }
-            super::ObjectTypeBound(ty, r) => tcx
-                .lift(&ty)
-                .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
-            super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
-            super::Coercion { source, target } => {
-                Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
-            }
-            super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
-            super::TupleInitializerSized => Some(super::TupleInitializerSized),
-            super::StructInitializerSized => Some(super::StructInitializerSized),
-            super::VariableType(id) => Some(super::VariableType(id)),
-            super::ReturnValue(id) => Some(super::ReturnValue(id)),
-            super::ReturnType => Some(super::ReturnType),
-            super::SizedArgumentType => Some(super::SizedArgumentType),
-            super::SizedReturnType => Some(super::SizedReturnType),
-            super::SizedYieldType => Some(super::SizedYieldType),
-            super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
-            super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
-            super::ConstSized => Some(super::ConstSized),
-            super::ConstPatternStructural => Some(super::ConstPatternStructural),
-            super::SharedStatic => Some(super::SharedStatic),
-            super::BuiltinDerivedObligation(ref cause) => {
-                tcx.lift(cause).map(super::BuiltinDerivedObligation)
-            }
-            super::ImplDerivedObligation(ref cause) => {
-                tcx.lift(cause).map(super::ImplDerivedObligation)
-            }
-            super::CompareImplMethodObligation {
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            } => Some(super::CompareImplMethodObligation {
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            }),
-            super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
-                Some(super::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                })
-            }
-            super::ExprAssignable => Some(super::ExprAssignable),
-            super::MatchExpressionArm(box super::MatchExpressionArmCause {
-                arm_span,
-                source,
-                ref prior_arms,
-                last_ty,
-                scrut_hir_id,
-            }) => tcx.lift(&last_ty).map(|last_ty| {
-                super::MatchExpressionArm(box super::MatchExpressionArmCause {
-                    arm_span,
-                    source,
-                    prior_arms: prior_arms.clone(),
-                    last_ty,
-                    scrut_hir_id,
-                })
-            }),
-            super::Pattern { span, root_ty, origin_expr } => {
-                tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
-            }
-            super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
-                Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
-            }
-            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
-            super::MainFunctionType => Some(super::MainFunctionType),
-            super::StartFunctionType => Some(super::StartFunctionType),
-            super::IntrinsicType => Some(super::IntrinsicType),
-            super::MethodReceiver => Some(super::MethodReceiver),
-            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
-            super::TrivialBound => Some(super::TrivialBound),
-            super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
-    type Lifted = traits::DerivedObligationCause<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
-            tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
-                parent_trait_ref: trait_ref,
-                parent_code: Rc::new(code),
-            })
-        })
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
-    type Lifted = traits::ObligationCause<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.code).map(|code| traits::ObligationCause {
-            span: self.span,
-            body_id: self.body_id,
-            code,
-        })
-    }
-}
-
-// For codegen only.
-impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
-    type Lifted = traits::Vtable<'tcx, ()>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match self.clone() {
-            traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
-                tcx.lift(&substs).map(|substs| {
-                    traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
-                })
-            }
-            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
-            traits::VtableGenerator(traits::VtableGeneratorData {
-                generator_def_id,
-                substs,
-                nested,
-            }) => tcx.lift(&substs).map(|substs| {
-                traits::VtableGenerator(traits::VtableGeneratorData {
-                    generator_def_id: generator_def_id,
-                    substs: substs,
-                    nested: nested,
-                })
-            }),
-            traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
-                tcx.lift(&substs).map(|substs| {
-                    traits::VtableClosure(traits::VtableClosureData {
-                        closure_def_id,
-                        substs,
-                        nested,
-                    })
-                })
-            }
-            traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
-                tcx.lift(&fn_ty).map(|fn_ty| {
-                    traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
-                })
-            }
-            traits::VtableParam(n) => Some(traits::VtableParam(n)),
-            traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
-            traits::VtableObject(traits::VtableObjectData {
-                upcast_trait_ref,
-                vtable_base,
-                nested,
-            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
-                traits::VtableObject(traits::VtableObjectData {
-                    upcast_trait_ref: trait_ref,
-                    vtable_base,
-                    nested,
-                })
-            }),
-            traits::VtableTraitAlias(traits::VtableTraitAliasData {
-                alias_def_id,
-                substs,
-                nested,
-            }) => tcx.lift(&substs).map(|substs| {
-                traits::VtableTraitAlias(traits::VtableTraitAliasData {
-                    alias_def_id,
-                    substs,
-                    nested,
-                })
-            }),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
-    type Lifted = traits::Environment<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
-    }
-}
-
-impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
-    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.environment).and_then(|environment| {
-            tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
-        })
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedExClause;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedDelayedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 
@@ -695,80 +69,3 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
         self.predicate.visit_with(visitor)
     }
 }
-
-CloneTypeFoldableAndLiftImpls! {
-    traits::QuantifierKind,
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
-        folder.tcx().intern_goals(&v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.iter().any(|t| t.visit_with(visitor))
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        let v = (**self).fold_with(folder);
-        folder.tcx().mk_goal(v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        (**self).visit_with(visitor)
-    }
-}
-
-CloneTypeFoldableAndLiftImpls! {
-    traits::ProgramClauseCategory,
-}
-
-impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
-        folder.tcx().intern_clauses(&v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.iter().any(|t| t.visit_with(visitor))
-    }
-}
-
-impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
-where
-    C: traits::ExClauseFold<'tcx>,
-    C::Substitution: Clone,
-    C::RegionConstraint: Clone,
-{
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
-        (chalk_engine::DelayedLiteral::CannotProve)(a),
-        (chalk_engine::DelayedLiteral::Negative)(a),
-        (chalk_engine::DelayedLiteral::Positive)(a, b),
-    } where
-        C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
-        (chalk_engine::Literal::Negative)(a),
-        (chalk_engine::Literal::Positive)(a),
-    } where
-        C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
-}
-
-CloneTypeFoldableAndLiftImpls! {
-    chalk_engine::TableIndex,
-}
diff --git a/src/librustc/traits/types/mod.rs b/src/librustc/traits/types/mod.rs
new file mode 100644
index 00000000000..571fb505779
--- /dev/null
+++ b/src/librustc/traits/types/mod.rs
@@ -0,0 +1,736 @@
+//! Trait Resolution. See the [rustc guide] for more information on how this works.
+//!
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
+
+pub mod query;
+pub mod select;
+pub mod specialization_graph;
+mod structural_impls;
+
+use crate::mir::interpret::ErrorHandled;
+use crate::ty::fold::{TypeFolder, TypeVisitor};
+use crate::ty::subst::SubstsRef;
+use crate::ty::{self, AdtKind, List, Ty, TyCtxt};
+
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::{Span, DUMMY_SP};
+use syntax::ast;
+
+use std::fmt::Debug;
+use std::rc::Rc;
+
+pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
+
+pub use self::ObligationCauseCode::*;
+pub use self::SelectionError::*;
+pub use self::Vtable::*;
+
+/// Depending on the stage of compilation, we want projection to be
+/// more or less conservative.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
+pub enum Reveal {
+    /// At type-checking time, we refuse to project any associated
+    /// type that is marked `default`. Non-`default` ("final") types
+    /// are always projected. This is necessary in general for
+    /// soundness of specialization. However, we *could* allow
+    /// projections in fully-monomorphic cases. We choose not to,
+    /// because we prefer for `default type` to force the type
+    /// definition to be treated abstractly by any consumers of the
+    /// impl. Concretely, that means that the following example will
+    /// fail to compile:
+    ///
+    /// ```
+    /// trait Assoc {
+    ///     type Output;
+    /// }
+    ///
+    /// impl<T> Assoc for T {
+    ///     default type Output = bool;
+    /// }
+    ///
+    /// fn main() {
+    ///     let <() as Assoc>::Output = true;
+    /// }
+    /// ```
+    UserFacing,
+
+    /// At codegen time, all monomorphic projections will succeed.
+    /// Also, `impl Trait` is normalized to the concrete type,
+    /// which has to be already collected by type-checking.
+    ///
+    /// NOTE: as `impl Trait`'s concrete type should *never*
+    /// be observable directly by the user, `Reveal::All`
+    /// should not be used by checks which may expose
+    /// type equality or type contents to the user.
+    /// There are some exceptions, e.g., around OIBITS and
+    /// transmute-checking, which expose some details, but
+    /// not the whole concrete type of the `impl Trait`.
+    All,
+}
+
+/// The reason why we incurred this obligation; used for error reporting.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ObligationCause<'tcx> {
+    pub span: Span,
+
+    /// The ID of the fn body that triggered this obligation. This is
+    /// used for region obligations to determine the precise
+    /// environment in which the region obligation should be evaluated
+    /// (in particular, closures can add new assumptions). See the
+    /// field `region_obligations` of the `FulfillmentContext` for more
+    /// information.
+    pub body_id: hir::HirId,
+
+    pub code: ObligationCauseCode<'tcx>,
+}
+
+impl<'tcx> ObligationCause<'tcx> {
+    #[inline]
+    pub fn new(
+        span: Span,
+        body_id: hir::HirId,
+        code: ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx> {
+        ObligationCause { span, body_id, code }
+    }
+
+    pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
+        ObligationCause { span, body_id, code: MiscObligation }
+    }
+
+    pub fn dummy() -> ObligationCause<'tcx> {
+        ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }
+    }
+
+    pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
+        match self.code {
+            ObligationCauseCode::CompareImplMethodObligation { .. }
+            | ObligationCauseCode::MainFunctionType
+            | ObligationCauseCode::StartFunctionType => tcx.sess.source_map().def_span(self.span),
+            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                arm_span,
+                ..
+            }) => arm_span,
+            _ => self.span,
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub enum ObligationCauseCode<'tcx> {
+    /// Not well classified or should be obvious from the span.
+    MiscObligation,
+
+    /// A slice or array is WF only if `T: Sized`.
+    SliceOrArrayElem,
+
+    /// A tuple is WF only if its middle elements are `Sized`.
+    TupleElem,
+
+    /// This is the trait reference from the given projection.
+    ProjectionWf(ty::ProjectionTy<'tcx>),
+
+    /// In an impl of trait `X` for type `Y`, type `Y` must
+    /// also implement all supertraits of `X`.
+    ItemObligation(DefId),
+
+    /// Like `ItemObligation`, but with extra detail on the source of the obligation.
+    BindingObligation(DefId, Span),
+
+    /// A type like `&'a T` is WF only if `T: 'a`.
+    ReferenceOutlivesReferent(Ty<'tcx>),
+
+    /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
+    ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
+
+    /// Obligation incurred due to an object cast.
+    ObjectCastObligation(/* Object type */ Ty<'tcx>),
+
+    /// Obligation incurred due to a coercion.
+    Coercion {
+        source: Ty<'tcx>,
+        target: Ty<'tcx>,
+    },
+
+    /// Various cases where expressions must be `Sized` / `Copy` / etc.
+    /// `L = X` implies that `L` is `Sized`.
+    AssignmentLhsSized,
+    /// `(x1, .., xn)` must be `Sized`.
+    TupleInitializerSized,
+    /// `S { ... }` must be `Sized`.
+    StructInitializerSized,
+    /// Type of each variable must be `Sized`.
+    VariableType(hir::HirId),
+    /// Argument type must be `Sized`.
+    SizedArgumentType,
+    /// Return type must be `Sized`.
+    SizedReturnType,
+    /// Yield type must be `Sized`.
+    SizedYieldType,
+    /// `[T, ..n]` implies that `T` must be `Copy`.
+    /// If `true`, suggest `const_in_array_repeat_expressions` feature flag.
+    RepeatVec(bool),
+
+    /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
+    FieldSized {
+        adt_kind: AdtKind,
+        last: bool,
+    },
+
+    /// Constant expressions must be sized.
+    ConstSized,
+
+    /// `static` items must have `Sync` type.
+    SharedStatic,
+
+    BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
+
+    ImplDerivedObligation(DerivedObligationCause<'tcx>),
+
+    /// Error derived when matching traits/impls; see ObligationCause for more details
+    CompareImplMethodObligation {
+        item_name: ast::Name,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    },
+
+    /// Error derived when matching traits/impls; see ObligationCause for more details
+    CompareImplTypeObligation {
+        item_name: ast::Name,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    },
+
+    /// Checking that this expression can be assigned where it needs to be
+    // FIXME(eddyb) #11161 is the original Expr required?
+    ExprAssignable,
+
+    /// Computing common supertype in the arms of a match expression
+    MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
+
+    /// Type error arising from type checking a pattern against an expected type.
+    Pattern {
+        /// The span of the scrutinee or type expression which caused the `root_ty` type.
+        span: Option<Span>,
+        /// The root expected type induced by a scrutinee or type expression.
+        root_ty: Ty<'tcx>,
+        /// Whether the `Span` came from an expression or a type expression.
+        origin_expr: bool,
+    },
+
+    /// Constants in patterns must have `Structural` type.
+    ConstPatternStructural,
+
+    /// Computing common supertype in an if expression
+    IfExpression(Box<IfExpressionCause>),
+
+    /// Computing common supertype of an if expression with no else counter-part
+    IfExpressionWithNoElse,
+
+    /// `main` has wrong type
+    MainFunctionType,
+
+    /// `start` has wrong type
+    StartFunctionType,
+
+    /// Intrinsic has wrong type
+    IntrinsicType,
+
+    /// Method receiver
+    MethodReceiver,
+
+    /// `return` with no expression
+    ReturnNoExpression,
+
+    /// `return` with an expression
+    ReturnValue(hir::HirId),
+
+    /// Return type of this function
+    ReturnType,
+
+    /// Block implicit return
+    BlockTailExpression(hir::HirId),
+
+    /// #[feature(trivial_bounds)] is not enabled
+    TrivialBound,
+
+    AssocTypeBound(Box<AssocTypeBoundData>),
+}
+
+impl ObligationCauseCode<'_> {
+    // Return the base obligation, ignoring derived obligations.
+    pub fn peel_derives(&self) -> &Self {
+        let mut base_cause = self;
+        while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
+            base_cause = &cause.parent_code;
+        }
+        base_cause
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct AssocTypeBoundData {
+    pub impl_span: Option<Span>,
+    pub original: Span,
+    pub bounds: Vec<Span>,
+}
+
+// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(ObligationCauseCode<'_>, 32);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct MatchExpressionArmCause<'tcx> {
+    pub arm_span: Span,
+    pub source: hir::MatchSource,
+    pub prior_arms: Vec<Span>,
+    pub last_ty: Ty<'tcx>,
+    pub scrut_hir_id: hir::HirId,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct IfExpressionCause {
+    pub then: Span,
+    pub outer: Option<Span>,
+    pub semicolon: Option<Span>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DerivedObligationCause<'tcx> {
+    /// The trait reference of the parent obligation that led to the
+    /// current obligation. Note that only trait obligations lead to
+    /// derived obligations, so we just store the trait reference here
+    /// directly.
+    pub parent_trait_ref: ty::PolyTraitRef<'tcx>,
+
+    /// The parent trait had this cause.
+    pub parent_code: Rc<ObligationCauseCode<'tcx>>,
+}
+
+/// The following types:
+/// * `WhereClause`,
+/// * `WellFormed`,
+/// * `FromEnv`,
+/// * `DomainGoal`,
+/// * `Goal`,
+/// * `Clause`,
+/// * `Environment`,
+/// * `InEnvironment`,
+/// are used for representing the trait system in the form of
+/// logic programming clauses. They are part of the interface
+/// for the chalk SLG solver.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
+pub enum WhereClause<'tcx> {
+    Implemented(ty::TraitPredicate<'tcx>),
+    ProjectionEq(ty::ProjectionPredicate<'tcx>),
+    RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
+    TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
+pub enum WellFormed<'tcx> {
+    Trait(ty::TraitPredicate<'tcx>),
+    Ty(Ty<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
+pub enum FromEnv<'tcx> {
+    Trait(ty::TraitPredicate<'tcx>),
+    Ty(Ty<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
+pub enum DomainGoal<'tcx> {
+    Holds(WhereClause<'tcx>),
+    WellFormed(WellFormed<'tcx>),
+    FromEnv(FromEnv<'tcx>),
+    Normalize(ty::ProjectionPredicate<'tcx>),
+}
+
+pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>;
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+pub enum QuantifierKind {
+    Universal,
+    Existential,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
+pub enum GoalKind<'tcx> {
+    Implies(Clauses<'tcx>, Goal<'tcx>),
+    And(Goal<'tcx>, Goal<'tcx>),
+    Not(Goal<'tcx>),
+    DomainGoal(DomainGoal<'tcx>),
+    Quantified(QuantifierKind, ty::Binder<Goal<'tcx>>),
+    Subtype(Ty<'tcx>, Ty<'tcx>),
+    CannotProve,
+}
+
+pub type Goal<'tcx> = &'tcx GoalKind<'tcx>;
+
+pub type Goals<'tcx> = &'tcx List<Goal<'tcx>>;
+
+impl<'tcx> DomainGoal<'tcx> {
+    pub fn into_goal(self) -> GoalKind<'tcx> {
+        GoalKind::DomainGoal(self)
+    }
+
+    pub fn into_program_clause(self) -> ProgramClause<'tcx> {
+        ProgramClause {
+            goal: self,
+            hypotheses: ty::List::empty(),
+            category: ProgramClauseCategory::Other,
+        }
+    }
+}
+
+impl<'tcx> GoalKind<'tcx> {
+    pub fn from_poly_domain_goal(
+        domain_goal: PolyDomainGoal<'tcx>,
+        tcx: TyCtxt<'tcx>,
+    ) -> GoalKind<'tcx> {
+        match domain_goal.no_bound_vars() {
+            Some(p) => p.into_goal(),
+            None => GoalKind::Quantified(
+                QuantifierKind::Universal,
+                domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal())),
+            ),
+        }
+    }
+}
+
+/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
+/// Harrop Formulas".
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+pub enum Clause<'tcx> {
+    Implies(ProgramClause<'tcx>),
+    ForAll(ty::Binder<ProgramClause<'tcx>>),
+}
+
+impl Clause<'tcx> {
+    pub fn category(self) -> ProgramClauseCategory {
+        match self {
+            Clause::Implies(clause) => clause.category,
+            Clause::ForAll(clause) => clause.skip_binder().category,
+        }
+    }
+}
+
+/// Multiple clauses.
+pub type Clauses<'tcx> = &'tcx List<Clause<'tcx>>;
+
+/// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
+/// that the domain goal `D` is true if `G1...Gn` are provable. This
+/// is equivalent to the implication `G1..Gn => D`; we usually write
+/// it with the reverse implication operator `:-` to emphasize the way
+/// that programs are actually solved (via backchaining, which starts
+/// with the goal to solve and proceeds from there).
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+pub struct ProgramClause<'tcx> {
+    /// This goal will be considered true ...
+    pub goal: DomainGoal<'tcx>,
+
+    /// ... if we can prove these hypotheses (there may be no hypotheses at all):
+    pub hypotheses: Goals<'tcx>,
+
+    /// Useful for filtering clauses.
+    pub category: ProgramClauseCategory,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+pub enum ProgramClauseCategory {
+    ImpliedBound,
+    WellFormed,
+    Other,
+}
+
+/// A set of clauses that we assume to be true.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+pub struct Environment<'tcx> {
+    pub clauses: Clauses<'tcx>,
+}
+
+impl Environment<'tcx> {
+    pub fn with<G>(self, goal: G) -> InEnvironment<'tcx, G> {
+        InEnvironment { environment: self, goal }
+    }
+}
+
+/// Something (usually a goal), along with an environment.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+pub struct InEnvironment<'tcx, G> {
+    pub environment: Environment<'tcx>,
+    pub goal: G,
+}
+
+#[derive(Clone, Debug, TypeFoldable)]
+pub enum SelectionError<'tcx> {
+    Unimplemented,
+    OutputTypeParameterMismatch(
+        ty::PolyTraitRef<'tcx>,
+        ty::PolyTraitRef<'tcx>,
+        ty::error::TypeError<'tcx>,
+    ),
+    TraitNotObjectSafe(DefId),
+    ConstEvalFailure(ErrorHandled),
+    Overflow,
+}
+
+/// When performing resolution, it is typically the case that there
+/// can be one of three outcomes:
+///
+/// - `Ok(Some(r))`: success occurred with result `r`
+/// - `Ok(None)`: could not definitely determine anything, usually due
+///   to inconclusive type inference.
+/// - `Err(e)`: error `e` occurred
+pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
+
+/// Given the successful resolution of an obligation, the `Vtable`
+/// indicates where the vtable comes from. Note that while we call this
+/// a "vtable", it does not necessarily indicate dynamic dispatch at
+/// runtime. `Vtable` instances just tell the compiler where to find
+/// methods, but in generic code those methods are typically statically
+/// dispatched -- only when an object is constructed is a `Vtable`
+/// instance reified into an actual vtable.
+///
+/// For example, the vtable may be tied to a specific impl (case A),
+/// or it may be relative to some bound that is in scope (case B).
+///
+/// ```
+/// impl<T:Clone> Clone<T> for Option<T> { ... } // Impl_1
+/// impl<T:Clone> Clone<T> for Box<T> { ... }    // Impl_2
+/// impl Clone for int { ... }             // Impl_3
+///
+/// fn foo<T:Clone>(concrete: Option<Box<int>>,
+///                 param: T,
+///                 mixed: Option<T>) {
+///
+///    // Case A: Vtable points at a specific impl. Only possible when
+///    // type is concretely known. If the impl itself has bounded
+///    // type parameters, Vtable will carry resolutions for those as well:
+///    concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
+///
+///    // Case B: Vtable must be provided by caller. This applies when
+///    // type is a type parameter.
+///    param.clone();    // VtableParam
+///
+///    // Case C: A mix of cases A and B.
+///    mixed.clone();    // Vtable(Impl_1, [VtableParam])
+/// }
+/// ```
+///
+/// ### The type parameter `N`
+///
+/// See explanation on `VtableImplData`.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub enum Vtable<'tcx, N> {
+    /// Vtable identifying a particular impl.
+    VtableImpl(VtableImplData<'tcx, N>),
+
+    /// Vtable for auto trait implementations.
+    /// This carries the information and nested obligations with regards
+    /// to an auto implementation for a trait `Trait`. The nested obligations
+    /// ensure the trait implementation holds for all the constituent types.
+    VtableAutoImpl(VtableAutoImplData<N>),
+
+    /// Successful resolution to an obligation provided by the caller
+    /// for some type parameter. The `Vec<N>` represents the
+    /// obligations incurred from normalizing the where-clause (if
+    /// any).
+    VtableParam(Vec<N>),
+
+    /// Virtual calls through an object.
+    VtableObject(VtableObjectData<'tcx, N>),
+
+    /// Successful resolution for a builtin trait.
+    VtableBuiltin(VtableBuiltinData<N>),
+
+    /// Vtable automatically generated for a closure. The `DefId` is the ID
+    /// of the closure expression. This is a `VtableImpl` in spirit, but the
+    /// impl is generated by the compiler and does not appear in the source.
+    VtableClosure(VtableClosureData<'tcx, N>),
+
+    /// Same as above, but for a function pointer type with the given signature.
+    VtableFnPointer(VtableFnPointerData<'tcx, N>),
+
+    /// Vtable automatically generated for a generator.
+    VtableGenerator(VtableGeneratorData<'tcx, N>),
+
+    /// Vtable for a trait alias.
+    VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
+}
+
+impl<'tcx, N> Vtable<'tcx, N> {
+    pub fn nested_obligations(self) -> Vec<N> {
+        match self {
+            VtableImpl(i) => i.nested,
+            VtableParam(n) => n,
+            VtableBuiltin(i) => i.nested,
+            VtableAutoImpl(d) => d.nested,
+            VtableClosure(c) => c.nested,
+            VtableGenerator(c) => c.nested,
+            VtableObject(d) => d.nested,
+            VtableFnPointer(d) => d.nested,
+            VtableTraitAlias(d) => d.nested,
+        }
+    }
+
+    pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M>
+    where
+        F: FnMut(N) -> M,
+    {
+        match self {
+            VtableImpl(i) => VtableImpl(VtableImplData {
+                impl_def_id: i.impl_def_id,
+                substs: i.substs,
+                nested: i.nested.into_iter().map(f).collect(),
+            }),
+            VtableParam(n) => VtableParam(n.into_iter().map(f).collect()),
+            VtableBuiltin(i) => {
+                VtableBuiltin(VtableBuiltinData { nested: i.nested.into_iter().map(f).collect() })
+            }
+            VtableObject(o) => VtableObject(VtableObjectData {
+                upcast_trait_ref: o.upcast_trait_ref,
+                vtable_base: o.vtable_base,
+                nested: o.nested.into_iter().map(f).collect(),
+            }),
+            VtableAutoImpl(d) => VtableAutoImpl(VtableAutoImplData {
+                trait_def_id: d.trait_def_id,
+                nested: d.nested.into_iter().map(f).collect(),
+            }),
+            VtableClosure(c) => VtableClosure(VtableClosureData {
+                closure_def_id: c.closure_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect(),
+            }),
+            VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
+                generator_def_id: c.generator_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect(),
+            }),
+            VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
+                fn_ty: p.fn_ty,
+                nested: p.nested.into_iter().map(f).collect(),
+            }),
+            VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
+                alias_def_id: d.alias_def_id,
+                substs: d.substs,
+                nested: d.nested.into_iter().map(f).collect(),
+            }),
+        }
+    }
+}
+
+/// Identifies a particular impl in the source, along with a set of
+/// substitutions from the impl's type/lifetime parameters. The
+/// `nested` vector corresponds to the nested obligations attached to
+/// the impl's type parameters.
+///
+/// The type parameter `N` indicates the type used for "nested
+/// obligations" that are required by the impl. During type-check, this
+/// is `Obligation`, as one might expect. During codegen, however, this
+/// is `()`, because codegen only requires a shallow resolution of an
+/// impl, and nested obligations are satisfied later.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableImplData<'tcx, N> {
+    pub impl_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableGeneratorData<'tcx, N> {
+    pub generator_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    /// Nested obligations. This can be non-empty if the generator
+    /// signature contains associated types.
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableClosureData<'tcx, N> {
+    pub closure_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    /// Nested obligations. This can be non-empty if the closure
+    /// signature contains associated types.
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableAutoImplData<N> {
+    pub trait_def_id: DefId,
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableBuiltinData<N> {
+    pub nested: Vec<N>,
+}
+
+/// A vtable for some object-safe trait `Foo` automatically derived
+/// for the object type `Foo`.
+#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableObjectData<'tcx, N> {
+    /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
+    pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
+
+    /// The vtable is formed by concatenating together the method lists of
+    /// the base object trait and all supertraits; this is the start of
+    /// `upcast_trait_ref`'s methods in that vtable.
+    pub vtable_base: usize,
+
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableFnPointerData<'tcx, N> {
+    pub fn_ty: Ty<'tcx>,
+    pub nested: Vec<N>,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VtableTraitAliasData<'tcx, N> {
+    pub alias_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    pub nested: Vec<N>,
+}
+
+pub trait ExClauseFold<'tcx>
+where
+    Self: chalk_engine::context::Context + Clone,
+{
+    fn fold_ex_clause_with<F: TypeFolder<'tcx>>(
+        ex_clause: &chalk_engine::ExClause<Self>,
+        folder: &mut F,
+    ) -> chalk_engine::ExClause<Self>;
+
+    fn visit_ex_clause_with<V: TypeVisitor<'tcx>>(
+        ex_clause: &chalk_engine::ExClause<Self>,
+        visitor: &mut V,
+    ) -> bool;
+}
+
+pub trait ChalkContextLift<'tcx>
+where
+    Self: chalk_engine::context::Context + Clone,
+{
+    type LiftedExClause: Debug + 'tcx;
+    type LiftedDelayedLiteral: Debug + 'tcx;
+    type LiftedLiteral: Debug + 'tcx;
+
+    fn lift_ex_clause_to_tcx(
+        ex_clause: &chalk_engine::ExClause<Self>,
+        tcx: TyCtxt<'tcx>,
+    ) -> Option<Self::LiftedExClause>;
+
+    fn lift_delayed_literal_to_tcx(
+        ex_clause: &chalk_engine::DelayedLiteral<Self>,
+        tcx: TyCtxt<'tcx>,
+    ) -> Option<Self::LiftedDelayedLiteral>;
+
+    fn lift_literal_to_tcx(
+        ex_clause: &chalk_engine::Literal<Self>,
+        tcx: TyCtxt<'tcx>,
+    ) -> Option<Self::LiftedLiteral>;
+}
diff --git a/src/librustc/traits/types/query.rs b/src/librustc/traits/types/query.rs
new file mode 100644
index 00000000000..c9055182620
--- /dev/null
+++ b/src/librustc/traits/types/query.rs
@@ -0,0 +1,332 @@
+//! Experimental types for the trait query interface. The methods
+//! defined in this module are all based on **canonicalization**,
+//! which makes a canonical query by replacing unbound inference
+//! variables and regions, so that results can be reused more broadly.
+//! The providers for the queries defined here can be found in
+//! `librustc_traits`.
+
+use crate::ich::StableHashingContext;
+use crate::infer::canonical::{Canonical, QueryResponse};
+use crate::ty::error::TypeError;
+use crate::ty::subst::GenericArg;
+use crate::ty::{self, Ty, TyCtxt};
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::struct_span_err;
+use rustc_span::source_map::Span;
+use std::iter::FromIterator;
+use std::mem;
+
+pub mod type_op {
+    use crate::ty::fold::TypeFoldable;
+    use crate::ty::subst::UserSubsts;
+    use crate::ty::{Predicate, Ty};
+    use rustc_hir::def_id::DefId;
+    use std::fmt;
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct AscribeUserType<'tcx> {
+        pub mir_ty: Ty<'tcx>,
+        pub def_id: DefId,
+        pub user_substs: UserSubsts<'tcx>,
+    }
+
+    impl<'tcx> AscribeUserType<'tcx> {
+        pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
+            Self { mir_ty, def_id, user_substs }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Eq<'tcx> {
+        pub a: Ty<'tcx>,
+        pub b: Ty<'tcx>,
+    }
+
+    impl<'tcx> Eq<'tcx> {
+        pub fn new(a: Ty<'tcx>, b: Ty<'tcx>) -> Self {
+            Self { a, b }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Subtype<'tcx> {
+        pub sub: Ty<'tcx>,
+        pub sup: Ty<'tcx>,
+    }
+
+    impl<'tcx> Subtype<'tcx> {
+        pub fn new(sub: Ty<'tcx>, sup: Ty<'tcx>) -> Self {
+            Self { sub, sup }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct ProvePredicate<'tcx> {
+        pub predicate: Predicate<'tcx>,
+    }
+
+    impl<'tcx> ProvePredicate<'tcx> {
+        pub fn new(predicate: Predicate<'tcx>) -> Self {
+            ProvePredicate { predicate }
+        }
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
+    pub struct Normalize<T> {
+        pub value: T,
+    }
+
+    impl<'tcx, T> Normalize<T>
+    where
+        T: fmt::Debug + TypeFoldable<'tcx>,
+    {
+        pub fn new(value: T) -> Self {
+            Self { value }
+        }
+    }
+}
+
+pub type CanonicalProjectionGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+
+pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
+
+pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
+
+pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
+
+pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
+
+pub type CanonicalTypeOpSubtypeGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
+
+pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
+
+pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
+
+#[derive(Clone, Debug, HashStable)]
+pub struct NoSolution;
+
+pub type Fallible<T> = Result<T, NoSolution>;
+
+impl<'tcx> From<TypeError<'tcx>> for NoSolution {
+    fn from(_: TypeError<'tcx>) -> NoSolution {
+        NoSolution
+    }
+}
+
+#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
+pub struct DropckOutlivesResult<'tcx> {
+    pub kinds: Vec<GenericArg<'tcx>>,
+    pub overflows: Vec<Ty<'tcx>>,
+}
+
+impl<'tcx> DropckOutlivesResult<'tcx> {
+    pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
+        if let Some(overflow_ty) = self.overflows.iter().next() {
+            let mut err = struct_span_err!(
+                tcx.sess,
+                span,
+                E0320,
+                "overflow while adding drop-check rules for {}",
+                ty,
+            );
+            err.note(&format!("overflowed on {}", overflow_ty));
+            err.emit();
+        }
+    }
+
+    pub fn into_kinds_reporting_overflows(
+        self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        ty: Ty<'tcx>,
+    ) -> Vec<GenericArg<'tcx>> {
+        self.report_overflows(tcx, span, ty);
+        let DropckOutlivesResult { kinds, overflows: _ } = self;
+        kinds
+    }
+}
+
+/// A set of constraints that need to be satisfied in order for
+/// a type to be valid for destruction.
+#[derive(Clone, Debug, HashStable)]
+pub struct DtorckConstraint<'tcx> {
+    /// Types that are required to be alive in order for this
+    /// type to be valid for destruction.
+    pub outlives: Vec<ty::subst::GenericArg<'tcx>>,
+
+    /// Types that could not be resolved: projections and params.
+    pub dtorck_types: Vec<Ty<'tcx>>,
+
+    /// If, during the computation of the dtorck constraint, we
+    /// overflow, that gets recorded here. The caller is expected to
+    /// report an error.
+    pub overflows: Vec<Ty<'tcx>>,
+}
+
+impl<'tcx> DtorckConstraint<'tcx> {
+    pub fn empty() -> DtorckConstraint<'tcx> {
+        DtorckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] }
+    }
+}
+
+impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
+    fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
+        let mut result = Self::empty();
+
+        for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
+            result.outlives.extend(outlives);
+            result.dtorck_types.extend(dtorck_types);
+            result.overflows.extend(overflows);
+        }
+
+        result
+    }
+}
+
+/// This returns true if the type `ty` is "trivial" for
+/// dropck-outlives -- that is, if it doesn't require any types to
+/// outlive. This is similar but not *quite* the same as the
+/// `needs_drop` test in the compiler already -- that is, for every
+/// type T for which this function return true, needs-drop would
+/// return `false`. But the reverse does not hold: in particular,
+/// `needs_drop` returns false for `PhantomData`, but it is not
+/// trivial for dropck-outlives.
+///
+/// Note also that `needs_drop` requires a "global" type (i.e., one
+/// with erased regions), but this function does not.
+pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.kind {
+        // None of these types have a destructor and hence they do not
+        // require anything in particular to outlive the dtor's
+        // execution.
+        ty::Infer(ty::FreshIntTy(_))
+        | ty::Infer(ty::FreshFloatTy(_))
+        | ty::Bool
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Never
+        | ty::FnDef(..)
+        | ty::FnPtr(_)
+        | ty::Char
+        | ty::GeneratorWitness(..)
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::Str
+        | ty::Foreign(..)
+        | ty::Error => true,
+
+        // [T; N] and [T] have same properties as T.
+        ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
+
+        // (T1..Tn) and closures have same properties as T1..Tn --
+        // check if *any* of those are trivial.
+        ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
+        ty::Closure(def_id, ref substs) => {
+            substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
+        }
+
+        ty::Adt(def, _) => {
+            if Some(def.did) == tcx.lang_items().manually_drop() {
+                // `ManuallyDrop` never has a dtor.
+                true
+            } else {
+                // Other types might. Moreover, PhantomData doesn't
+                // have a dtor, but it is considered to own its
+                // content, so it is non-trivial. Unions can have `impl Drop`,
+                // and hence are non-trivial as well.
+                false
+            }
+        }
+
+        // The following *might* require a destructor: needs deeper inspection.
+        ty::Dynamic(..)
+        | ty::Projection(..)
+        | ty::Param(_)
+        | ty::Opaque(..)
+        | ty::Placeholder(..)
+        | ty::Infer(_)
+        | ty::Bound(..)
+        | ty::Generator(..) => false,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+    }
+}
+
+#[derive(Debug, HashStable)]
+pub struct CandidateStep<'tcx> {
+    pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
+    pub autoderefs: usize,
+    /// `true` if the type results from a dereference of a raw pointer.
+    /// when assembling candidates, we include these steps, but not when
+    /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
+    /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
+    /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
+    pub from_unsafe_deref: bool,
+    pub unsize: bool,
+}
+
+#[derive(Clone, Debug, HashStable)]
+pub struct MethodAutoderefStepsResult<'tcx> {
+    /// The valid autoderef steps that could be find.
+    pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
+    /// If Some(T), a type autoderef reported an error on.
+    pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
+    /// If `true`, `steps` has been truncated due to reaching the
+    /// recursion limit.
+    pub reached_recursion_limit: bool,
+}
+
+#[derive(Debug, HashStable)]
+pub struct MethodAutoderefBadTy<'tcx> {
+    pub reached_raw_pointer: bool,
+    pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
+}
+
+/// Result from the `normalize_projection_ty` query.
+#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
+pub struct NormalizationResult<'tcx> {
+    /// Result of normalization.
+    pub normalized_ty: Ty<'tcx>,
+}
+
+/// Outlives bounds are relationships between generic parameters,
+/// whether they both be regions (`'a: 'b`) or whether types are
+/// involved (`T: 'a`). These relationships can be extracted from the
+/// full set of predicates we understand or also from types (in which
+/// case they are called implied bounds). They are fed to the
+/// `OutlivesEnv` which in turn is supplied to the region checker and
+/// other parts of the inference system.
+#[derive(Clone, Debug, TypeFoldable, Lift)]
+pub enum OutlivesBound<'tcx> {
+    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
+    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
+    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            OutlivesBound::RegionSubRegion(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            OutlivesBound::RegionSubParam(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            OutlivesBound::RegionSubProjection(ref a, ref b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
diff --git a/src/librustc/traits/types/select.rs b/src/librustc/traits/types/select.rs
new file mode 100644
index 00000000000..ac3d0049c0c
--- /dev/null
+++ b/src/librustc/traits/types/select.rs
@@ -0,0 +1,290 @@
+//! Candidate selection. See the [rustc guide] for more information on how this works.
+//!
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
+
+use self::EvaluationResult::*;
+
+use super::{SelectionError, SelectionResult};
+
+use crate::dep_graph::DepNodeIndex;
+use crate::ty::{self, TyCtxt};
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lock;
+use rustc_hir::def_id::DefId;
+
+#[derive(Clone, Default)]
+pub struct SelectionCache<'tcx> {
+    pub hashmap: Lock<
+        FxHashMap<
+            ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
+            WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>,
+        >,
+    >,
+}
+
+impl<'tcx> SelectionCache<'tcx> {
+    /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
+    pub fn clear(&self) {
+        *self.hashmap.borrow_mut() = Default::default();
+    }
+}
+
+/// The selection process begins by considering all impls, where
+/// clauses, and so forth that might resolve an obligation. Sometimes
+/// we'll be able to say definitively that (e.g.) an impl does not
+/// apply to the obligation: perhaps it is defined for `usize` but the
+/// obligation is for `int`. In that case, we drop the impl out of the
+/// list. But the other cases are considered *candidates*.
+///
+/// For selection to succeed, there must be exactly one matching
+/// candidate. If the obligation is fully known, this is guaranteed
+/// by coherence. However, if the obligation contains type parameters
+/// or variables, there may be multiple such impls.
+///
+/// It is not a real problem if multiple matching impls exist because
+/// of type variables - it just means the obligation isn't sufficiently
+/// elaborated. In that case we report an ambiguity, and the caller can
+/// try again after more type information has been gathered or report a
+/// "type annotations needed" error.
+///
+/// However, with type parameters, this can be a real problem - type
+/// parameters don't unify with regular types, but they *can* unify
+/// with variables from blanket impls, and (unless we know its bounds
+/// will always be satisfied) picking the blanket impl will be wrong
+/// for at least *some* substitutions. To make this concrete, if we have
+///
+///    trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
+///    impl<T: fmt::Debug> AsDebug for T {
+///        type Out = T;
+///        fn debug(self) -> fmt::Debug { self }
+///    }
+///    fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
+///
+/// we can't just use the impl to resolve the `<T as AsDebug>` obligation
+/// -- a type from another crate (that doesn't implement `fmt::Debug`) could
+/// implement `AsDebug`.
+///
+/// Because where-clauses match the type exactly, multiple clauses can
+/// only match if there are unresolved variables, and we can mostly just
+/// report this ambiguity in that case. This is still a problem - we can't
+/// *do anything* with ambiguities that involve only regions. This is issue
+/// #21974.
+///
+/// If a single where-clause matches and there are no inference
+/// variables left, then it definitely matches and we can just select
+/// it.
+///
+/// In fact, we even select the where-clause when the obligation contains
+/// inference variables. The can lead to inference making "leaps of logic",
+/// for example in this situation:
+///
+///    pub trait Foo<T> { fn foo(&self) -> T; }
+///    impl<T> Foo<()> for T { fn foo(&self) { } }
+///    impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
+///
+///    pub fn foo<T>(t: T) where T: Foo<bool> {
+///       println!("{:?}", <T as Foo<_>>::foo(&t));
+///    }
+///    fn main() { foo(false); }
+///
+/// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
+/// impl and the where-clause. We select the where-clause and unify `$0=bool`,
+/// so the program prints "false". However, if the where-clause is omitted,
+/// the blanket impl is selected, we unify `$0=()`, and the program prints
+/// "()".
+///
+/// Exactly the same issues apply to projection and object candidates, except
+/// that we can have both a projection candidate and a where-clause candidate
+/// for the same obligation. In that case either would do (except that
+/// different "leaps of logic" would occur if inference variables are
+/// present), and we just pick the where-clause. This is, for example,
+/// required for associated types to work in default impls, as the bounds
+/// are visible both as projection bounds and as where-clauses from the
+/// parameter environment.
+#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
+pub enum SelectionCandidate<'tcx> {
+    BuiltinCandidate {
+        /// `false` if there are no *further* obligations.
+        has_nested: bool,
+    },
+    ParamCandidate(ty::PolyTraitRef<'tcx>),
+    ImplCandidate(DefId),
+    AutoImplCandidate(DefId),
+
+    /// This is a trait matching with a projected type as `Self`, and
+    /// we found an applicable bound in the trait definition.
+    ProjectionCandidate,
+
+    /// Implementation of a `Fn`-family trait by one of the anonymous types
+    /// generated for a `||` expression.
+    ClosureCandidate,
+
+    /// Implementation of a `Generator` trait by one of the anonymous types
+    /// generated for a generator.
+    GeneratorCandidate,
+
+    /// Implementation of a `Fn`-family trait by one of the anonymous
+    /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
+    FnPointerCandidate,
+
+    TraitAliasCandidate(DefId),
+
+    ObjectCandidate,
+
+    BuiltinObjectCandidate,
+
+    BuiltinUnsizeCandidate,
+}
+
+/// The result of trait evaluation. The order is important
+/// here as the evaluation of a list is the maximum of the
+/// evaluations.
+///
+/// The evaluation results are ordered:
+///     - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
+///       implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
+///     - `EvaluatedToErr` implies `EvaluatedToRecur`
+///     - the "union" of evaluation results is equal to their maximum -
+///     all the "potential success" candidates can potentially succeed,
+///     so they are noops when unioned with a definite error, and within
+///     the categories it's easy to see that the unions are correct.
+#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
+pub enum EvaluationResult {
+    /// Evaluation successful.
+    EvaluatedToOk,
+    /// Evaluation successful, but there were unevaluated region obligations.
+    EvaluatedToOkModuloRegions,
+    /// Evaluation is known to be ambiguous -- it *might* hold for some
+    /// assignment of inference variables, but it might not.
+    ///
+    /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
+    /// know whether this obligation holds or not -- it is the result we
+    /// would get with an empty stack, and therefore is cacheable.
+    EvaluatedToAmbig,
+    /// Evaluation failed because of recursion involving inference
+    /// variables. We are somewhat imprecise there, so we don't actually
+    /// know the real result.
+    ///
+    /// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
+    EvaluatedToUnknown,
+    /// Evaluation failed because we encountered an obligation we are already
+    /// trying to prove on this branch.
+    ///
+    /// We know this branch can't be a part of a minimal proof-tree for
+    /// the "root" of our cycle, because then we could cut out the recursion
+    /// and maintain a valid proof tree. However, this does not mean
+    /// that all the obligations on this branch do not hold -- it's possible
+    /// that we entered this branch "speculatively", and that there
+    /// might be some other way to prove this obligation that does not
+    /// go through this cycle -- so we can't cache this as a failure.
+    ///
+    /// For example, suppose we have this:
+    ///
+    /// ```rust,ignore (pseudo-Rust)
+    /// pub trait Trait { fn xyz(); }
+    /// // This impl is "useless", but we can still have
+    /// // an `impl Trait for SomeUnsizedType` somewhere.
+    /// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
+    ///
+    /// pub fn foo<T: Trait + ?Sized>() {
+    ///     <T as Trait>::xyz();
+    /// }
+    /// ```
+    ///
+    /// When checking `foo`, we have to prove `T: Trait`. This basically
+    /// translates into this:
+    ///
+    /// ```plain,ignore
+    /// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
+    /// ```
+    ///
+    /// When we try to prove it, we first go the first option, which
+    /// recurses. This shows us that the impl is "useless" -- it won't
+    /// tell us that `T: Trait` unless it already implemented `Trait`
+    /// by some other means. However, that does not prevent `T: Trait`
+    /// does not hold, because of the bound (which can indeed be satisfied
+    /// by `SomeUnsizedType` from another crate).
+    //
+    // FIXME: when an `EvaluatedToRecur` goes past its parent root, we
+    // ought to convert it to an `EvaluatedToErr`, because we know
+    // there definitely isn't a proof tree for that obligation. Not
+    // doing so is still sound -- there isn't any proof tree, so the
+    // branch still can't be a part of a minimal one -- but does not re-enable caching.
+    EvaluatedToRecur,
+    /// Evaluation failed.
+    EvaluatedToErr,
+}
+
+impl EvaluationResult {
+    /// Returns `true` if this evaluation result is known to apply, even
+    /// considering outlives constraints.
+    pub fn must_apply_considering_regions(self) -> bool {
+        self == EvaluatedToOk
+    }
+
+    /// Returns `true` if this evaluation result is known to apply, ignoring
+    /// outlives constraints.
+    pub fn must_apply_modulo_regions(self) -> bool {
+        self <= EvaluatedToOkModuloRegions
+    }
+
+    pub fn may_apply(self) -> bool {
+        match self {
+            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
+                true
+            }
+
+            EvaluatedToErr | EvaluatedToRecur => false,
+        }
+    }
+
+    pub fn is_stack_dependent(self) -> bool {
+        match self {
+            EvaluatedToUnknown | EvaluatedToRecur => true,
+
+            EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
+        }
+    }
+}
+
+/// Indicates that trait evaluation caused overflow.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
+pub struct OverflowError;
+
+impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
+    fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
+        SelectionError::Overflow
+    }
+}
+
+#[derive(Clone, Default)]
+pub struct EvaluationCache<'tcx> {
+    pub hashmap: Lock<
+        FxHashMap<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, WithDepNode<EvaluationResult>>,
+    >,
+}
+
+impl<'tcx> EvaluationCache<'tcx> {
+    /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
+    pub fn clear(&self) {
+        *self.hashmap.borrow_mut() = Default::default();
+    }
+}
+
+#[derive(Clone, Eq, PartialEq)]
+pub struct WithDepNode<T> {
+    dep_node: DepNodeIndex,
+    cached_value: T,
+}
+
+impl<T: Clone> WithDepNode<T> {
+    pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
+        WithDepNode { dep_node, cached_value }
+    }
+
+    pub fn get(&self, tcx: TyCtxt<'_>) -> T {
+        tcx.dep_graph.read_index(self.dep_node);
+        self.cached_value.clone()
+    }
+}
diff --git a/src/librustc/traits/types/specialization_graph.rs b/src/librustc/traits/types/specialization_graph.rs
new file mode 100644
index 00000000000..3086850db6d
--- /dev/null
+++ b/src/librustc/traits/types/specialization_graph.rs
@@ -0,0 +1,199 @@
+use crate::ich::{self, StableHashingContext};
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::{self, TyCtxt};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def_id::{DefId, DefIdMap};
+use syntax::ast::Ident;
+
+/// A per-trait graph of impls in specialization order. At the moment, this
+/// graph forms a tree rooted with the trait itself, with all other nodes
+/// representing impls, and parent-child relationships representing
+/// specializations.
+///
+/// The graph provides two key services:
+///
+/// - Construction. This implicitly checks for overlapping impls (i.e., impls
+///   that overlap but where neither specializes the other -- an artifact of the
+///   simple "chain" rule.
+///
+/// - Parent extraction. In particular, the graph can give you the *immediate*
+///   parents of a given specializing impl, which is needed for extracting
+///   default items amongst other things. In the simple "chain" rule, every impl
+///   has at most one parent.
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
+pub struct Graph {
+    // All impls have a parent; the "root" impls have as their parent the `def_id`
+    // of the trait.
+    pub parent: DefIdMap<DefId>,
+
+    // The "root" impls are found by looking up the trait's def_id.
+    pub children: DefIdMap<Children>,
+}
+
+impl Graph {
+    pub fn new() -> Graph {
+        Graph { parent: Default::default(), children: Default::default() }
+    }
+
+    /// The parent of a given impl, which is the `DefId` of the trait when the
+    /// impl is a "specialization root".
+    pub fn parent(&self, child: DefId) -> DefId {
+        *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {:?}", child))
+    }
+}
+
+/// Children of a given impl, grouped into blanket/non-blanket varieties as is
+/// done in `TraitDef`.
+#[derive(Default, RustcEncodable, RustcDecodable)]
+pub struct Children {
+    // Impls of a trait (or specializations of a given impl). To allow for
+    // quicker lookup, the impls are indexed by a simplified version of their
+    // `Self` type: impls with a simplifiable `Self` are stored in
+    // `nonblanket_impls` keyed by it, while all other impls are stored in
+    // `blanket_impls`.
+    //
+    // A similar division is used within `TraitDef`, but the lists there collect
+    // together *all* the impls for a trait, and are populated prior to building
+    // the specialization graph.
+    /// Impls of the trait.
+    pub nonblanket_impls: FxHashMap<SimplifiedType, Vec<DefId>>,
+
+    /// Blanket impls associated with the trait.
+    pub blanket_impls: Vec<DefId>,
+}
+
+/// A node in the specialization graph is either an impl or a trait
+/// definition; either can serve as a source of item definitions.
+/// There is always exactly one trait definition node: the root.
+#[derive(Debug, Copy, Clone)]
+pub enum Node {
+    Impl(DefId),
+    Trait(DefId),
+}
+
+impl<'tcx> Node {
+    pub fn is_from_trait(&self) -> bool {
+        match *self {
+            Node::Trait(..) => true,
+            _ => false,
+        }
+    }
+
+    /// Iterate over the items defined directly by the given (impl or trait) node.
+    pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> {
+        tcx.associated_items(self.def_id())
+    }
+
+    /// Finds an associated item defined in this node.
+    ///
+    /// If this returns `None`, the item can potentially still be found in
+    /// parents of this node.
+    pub fn item(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        trait_item_name: Ident,
+        trait_item_kind: ty::AssocKind,
+        trait_def_id: DefId,
+    ) -> Option<ty::AssocItem> {
+        use crate::ty::AssocKind::*;
+
+        tcx.associated_items(self.def_id()).find(move |impl_item| {
+            match (trait_item_kind, impl_item.kind) {
+                | (Const, Const)
+                | (Method, Method)
+                | (Type, Type)
+                | (Type, OpaqueTy)  // assoc. types can be made opaque in impls
+                => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id),
+
+                | (Const, _)
+                | (Method, _)
+                | (Type, _)
+                | (OpaqueTy, _)
+                => false,
+            }
+        })
+    }
+
+    pub fn def_id(&self) -> DefId {
+        match *self {
+            Node::Impl(did) => did,
+            Node::Trait(did) => did,
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct Ancestors<'tcx> {
+    trait_def_id: DefId,
+    specialization_graph: &'tcx Graph,
+    current_source: Option<Node>,
+}
+
+impl Iterator for Ancestors<'_> {
+    type Item = Node;
+    fn next(&mut self) -> Option<Node> {
+        let cur = self.current_source.take();
+        if let Some(Node::Impl(cur_impl)) = cur {
+            let parent = self.specialization_graph.parent(cur_impl);
+
+            self.current_source = if parent == self.trait_def_id {
+                Some(Node::Trait(parent))
+            } else {
+                Some(Node::Impl(parent))
+            };
+        }
+        cur
+    }
+}
+
+pub struct NodeItem<T> {
+    pub node: Node,
+    pub item: T,
+}
+
+impl<T> NodeItem<T> {
+    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
+        NodeItem { node: self.node, item: f(self.item) }
+    }
+}
+
+impl<'tcx> Ancestors<'tcx> {
+    /// Finds the bottom-most (ie. most specialized) definition of an associated
+    /// item.
+    pub fn leaf_def(
+        mut self,
+        tcx: TyCtxt<'tcx>,
+        trait_item_name: Ident,
+        trait_item_kind: ty::AssocKind,
+    ) -> Option<NodeItem<ty::AssocItem>> {
+        let trait_def_id = self.trait_def_id;
+        self.find_map(|node| {
+            node.item(tcx, trait_item_name, trait_item_kind, trait_def_id)
+                .map(|item| NodeItem { node, item })
+        })
+    }
+}
+
+/// Walk up the specialization ancestors of a given impl, starting with that
+/// impl itself.
+pub fn ancestors(
+    tcx: TyCtxt<'tcx>,
+    trait_def_id: DefId,
+    start_from_impl: DefId,
+) -> Ancestors<'tcx> {
+    let specialization_graph = tcx.specialization_graph_of(trait_def_id);
+    Ancestors {
+        trait_def_id,
+        specialization_graph,
+        current_source: Some(Node::Impl(start_from_impl)),
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for Children {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        let Children { ref nonblanket_impls, ref blanket_impls } = *self;
+
+        ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls);
+    }
+}
diff --git a/src/librustc/traits/types/structural_impls.rs b/src/librustc/traits/types/structural_impls.rs
new file mode 100644
index 00000000000..48ed29f2bb3
--- /dev/null
+++ b/src/librustc/traits/types/structural_impls.rs
@@ -0,0 +1,712 @@
+use crate::traits;
+use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::{self, Lift, Ty, TyCtxt};
+use rustc_span::symbol::Symbol;
+use smallvec::SmallVec;
+
+use std::collections::{BTreeMap, BTreeSet};
+use std::fmt;
+use std::rc::Rc;
+
+// Structural impls for the structs in `traits`.
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            super::VtableImpl(ref v) => write!(f, "{:?}", v),
+
+            super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
+
+            super::VtableClosure(ref d) => write!(f, "{:?}", d),
+
+            super::VtableGenerator(ref d) => write!(f, "{:?}", d),
+
+            super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
+
+            super::VtableObject(ref d) => write!(f, "{:?}", d),
+
+            super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
+
+            super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
+
+            super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
+        }
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
+            self.impl_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
+            self.generator_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
+            self.closure_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "VtableBuiltinData(nested={:?})", self.nested)
+    }
+}
+
+impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
+            self.trait_def_id, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
+            self.upcast_trait_ref, self.vtable_base, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
+            self.alias_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::WhereClause::*;
+
+        // Bypass `ty::print` because it does not print out anonymous regions.
+        // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
+        fn write_region_name<'tcx>(
+            r: ty::Region<'tcx>,
+            fmt: &mut fmt::Formatter<'_>,
+        ) -> fmt::Result {
+            match r {
+                ty::ReLateBound(index, br) => match br {
+                    ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
+                    ty::BoundRegion::BrAnon(var) => {
+                        if *index == ty::INNERMOST {
+                            write!(fmt, "'^{}", var)
+                        } else {
+                            write!(fmt, "'^{}_{}", index.index(), var)
+                        }
+                    }
+                    _ => write!(fmt, "'_"),
+                },
+
+                _ => write!(fmt, "{}", r),
+            }
+        }
+
+        match self {
+            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+            RegionOutlives(predicate) => {
+                write!(fmt, "RegionOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+            TypeOutlives(predicate) => {
+                write!(fmt, "TypeOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::WellFormed::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
+            Ty(ty) => write!(fmt, "WellFormed({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::FromEnv::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
+            Ty(ty) => write!(fmt, "FromEnv({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::DomainGoal::*;
+
+        match self {
+            Holds(wc) => write!(fmt, "{}", wc),
+            WellFormed(wf) => write!(fmt, "{}", wf),
+            FromEnv(from_env) => write!(fmt, "{}", from_env),
+            Normalize(projection) => {
+                write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
+            }
+        }
+    }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::QuantifierKind::*;
+
+        match self {
+            Universal => write!(fmt, "forall"),
+            Existential => write!(fmt, "exists"),
+        }
+    }
+}
+
+/// Collect names for regions / types bound by a quantified goal / clause.
+/// This collector does not try to do anything clever like in `ty::print`, it's just used
+/// for debug output in tests anyway.
+struct BoundNamesCollector {
+    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
+    regions: BTreeSet<Symbol>,
+
+    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
+    // by the list of type parameters.
+    types: BTreeMap<u32, Symbol>,
+
+    binder_index: ty::DebruijnIndex,
+}
+
+impl BoundNamesCollector {
+    fn new() -> Self {
+        BoundNamesCollector {
+            regions: BTreeSet::new(),
+            types: BTreeMap::new(),
+            binder_index: ty::INNERMOST,
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.regions.is_empty() && self.types.is_empty()
+    }
+
+    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut start = true;
+        for r in &self.regions {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", r)?;
+        }
+        for (_, t) in &self.types {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", t)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
+    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+        match t.kind {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
+                self.types.insert(
+                    bound_ty.var.as_u32(),
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Param(name) => name,
+                        ty::BoundTyKind::Anon => {
+                            Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
+                        }
+                    },
+                );
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
+                ty::BoundRegion::BrNamed(_, name) => {
+                    self.regions.insert(*name);
+                }
+
+                ty::BoundRegion::BrAnon(var) => {
+                    self.regions.insert(Symbol::intern(&format!("'^{}", var)));
+                }
+
+                _ => (),
+            },
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::GoalKind::*;
+
+        match self {
+            Implies(hypotheses, goal) => {
+                write!(fmt, "if (")?;
+                for (index, hyp) in hypotheses.iter().enumerate() {
+                    if index > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{}", hyp)?;
+                }
+                write!(fmt, ") {{ {} }}", goal)
+            }
+            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+            Not(goal) => write!(fmt, "not {{ {} }}", goal),
+            DomainGoal(goal) => write!(fmt, "{}", goal),
+            Quantified(qkind, goal) => {
+                let mut collector = BoundNamesCollector::new();
+                goal.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "{}<", qkind)?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", goal.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+            Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
+            CannotProve => write!(fmt, "CannotProve"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let traits::ProgramClause { goal, hypotheses, .. } = self;
+        write!(fmt, "{}", goal)?;
+        if !hypotheses.is_empty() {
+            write!(fmt, " :- ")?;
+            for (index, condition) in hypotheses.iter().enumerate() {
+                if index > 0 {
+                    write!(fmt, ", ")?;
+                }
+                write!(fmt, "{}", condition)?;
+            }
+        }
+        write!(fmt, ".")
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::Clause::*;
+
+        match self {
+            Implies(clause) => write!(fmt, "{}", clause),
+            ForAll(clause) => {
+                let mut collector = BoundNamesCollector::new();
+                clause.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "forall<")?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", clause.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Lift implementations
+
+impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
+    type Lifted = traits::SelectionError<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            super::Unimplemented => Some(super::Unimplemented),
+            super::OutputTypeParameterMismatch(a, b, ref err) => {
+                tcx.lift(&(a, b)).and_then(|(a, b)| {
+                    tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
+                })
+            }
+            super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
+            super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
+            super::Overflow => Some(super::Overflow),
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
+    type Lifted = traits::ObligationCauseCode<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            super::ReturnNoExpression => Some(super::ReturnNoExpression),
+            super::MiscObligation => Some(super::MiscObligation),
+            super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
+            super::TupleElem => Some(super::TupleElem),
+            super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
+            super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
+            super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
+            super::ReferenceOutlivesReferent(ty) => {
+                tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
+            }
+            super::ObjectTypeBound(ty, r) => tcx
+                .lift(&ty)
+                .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
+            super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
+            super::Coercion { source, target } => {
+                Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
+            }
+            super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
+            super::TupleInitializerSized => Some(super::TupleInitializerSized),
+            super::StructInitializerSized => Some(super::StructInitializerSized),
+            super::VariableType(id) => Some(super::VariableType(id)),
+            super::ReturnValue(id) => Some(super::ReturnValue(id)),
+            super::ReturnType => Some(super::ReturnType),
+            super::SizedArgumentType => Some(super::SizedArgumentType),
+            super::SizedReturnType => Some(super::SizedReturnType),
+            super::SizedYieldType => Some(super::SizedYieldType),
+            super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
+            super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
+            super::ConstSized => Some(super::ConstSized),
+            super::ConstPatternStructural => Some(super::ConstPatternStructural),
+            super::SharedStatic => Some(super::SharedStatic),
+            super::BuiltinDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::BuiltinDerivedObligation)
+            }
+            super::ImplDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::ImplDerivedObligation)
+            }
+            super::CompareImplMethodObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => Some(super::CompareImplMethodObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            }),
+            super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
+                Some(super::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                })
+            }
+            super::ExprAssignable => Some(super::ExprAssignable),
+            super::MatchExpressionArm(box super::MatchExpressionArmCause {
+                arm_span,
+                source,
+                ref prior_arms,
+                last_ty,
+                scrut_hir_id,
+            }) => tcx.lift(&last_ty).map(|last_ty| {
+                super::MatchExpressionArm(box super::MatchExpressionArmCause {
+                    arm_span,
+                    source,
+                    prior_arms: prior_arms.clone(),
+                    last_ty,
+                    scrut_hir_id,
+                })
+            }),
+            super::Pattern { span, root_ty, origin_expr } => {
+                tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
+            }
+            super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
+                Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
+            }
+            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
+            super::MainFunctionType => Some(super::MainFunctionType),
+            super::StartFunctionType => Some(super::StartFunctionType),
+            super::IntrinsicType => Some(super::IntrinsicType),
+            super::MethodReceiver => Some(super::MethodReceiver),
+            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
+            super::TrivialBound => Some(super::TrivialBound),
+            super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
+    type Lifted = traits::DerivedObligationCause<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
+            tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
+                parent_trait_ref: trait_ref,
+                parent_code: Rc::new(code),
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
+    type Lifted = traits::ObligationCause<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.code).map(|code| traits::ObligationCause {
+            span: self.span,
+            body_id: self.body_id,
+            code,
+        })
+    }
+}
+
+// For codegen only.
+impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
+    type Lifted = traits::Vtable<'tcx, ()>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match self.clone() {
+            traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
+                tcx.lift(&substs).map(|substs| {
+                    traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
+                })
+            }
+            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
+            traits::VtableGenerator(traits::VtableGeneratorData {
+                generator_def_id,
+                substs,
+                nested,
+            }) => tcx.lift(&substs).map(|substs| {
+                traits::VtableGenerator(traits::VtableGeneratorData {
+                    generator_def_id: generator_def_id,
+                    substs: substs,
+                    nested: nested,
+                })
+            }),
+            traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
+                tcx.lift(&substs).map(|substs| {
+                    traits::VtableClosure(traits::VtableClosureData {
+                        closure_def_id,
+                        substs,
+                        nested,
+                    })
+                })
+            }
+            traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
+                tcx.lift(&fn_ty).map(|fn_ty| {
+                    traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
+                })
+            }
+            traits::VtableParam(n) => Some(traits::VtableParam(n)),
+            traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
+            traits::VtableObject(traits::VtableObjectData {
+                upcast_trait_ref,
+                vtable_base,
+                nested,
+            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
+                traits::VtableObject(traits::VtableObjectData {
+                    upcast_trait_ref: trait_ref,
+                    vtable_base,
+                    nested,
+                })
+            }),
+            traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                alias_def_id,
+                substs,
+                nested,
+            }) => tcx.lift(&substs).map(|substs| {
+                traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                    alias_def_id,
+                    substs,
+                    nested,
+                })
+            }),
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
+    type Lifted = traits::Environment<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
+    }
+}
+
+impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
+    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.environment).and_then(|environment| {
+            tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
+        })
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedExClause;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedDelayedLiteral;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedLiteral;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// TypeFoldable implementations.
+
+CloneTypeFoldableAndLiftImpls! {
+    traits::QuantifierKind,
+}
+
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
+        folder.tcx().intern_goals(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        let v = (**self).fold_with(folder);
+        folder.tcx().mk_goal(v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        (**self).visit_with(visitor)
+    }
+}
+
+CloneTypeFoldableAndLiftImpls! {
+    traits::ProgramClauseCategory,
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
+        folder.tcx().intern_clauses(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
+
+impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
+where
+    C: traits::ExClauseFold<'tcx>,
+    C::Substitution: Clone,
+    C::RegionConstraint: Clone,
+{
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
+    }
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
+        (chalk_engine::DelayedLiteral::CannotProve)(a),
+        (chalk_engine::DelayedLiteral::Negative)(a),
+        (chalk_engine::DelayedLiteral::Positive)(a, b),
+    } where
+        C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
+        (chalk_engine::Literal::Negative)(a),
+        (chalk_engine::Literal::Positive)(a),
+    } where
+        C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
+}
+
+CloneTypeFoldableAndLiftImpls! {
+    chalk_engine::TableIndex,
+}
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 217ca0ca3f6..0282f409b32 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -15,6 +15,16 @@ pub struct ExpectedFound<T> {
     pub found: T,
 }
 
+impl<T> ExpectedFound<T> {
+    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
+        if a_is_expected {
+            ExpectedFound { expected: a, found: b }
+        } else {
+            ExpectedFound { expected: b, found: a }
+        }
+    }
+}
+
 // Data structures used in type unification
 #[derive(Clone, Debug, TypeFoldable)]
 pub enum TypeError<'tcx> {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 0781feee845..2538322431e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -46,7 +46,6 @@ use rustc_target::abi::Align;
 use syntax::ast::{self, Constness, Ident, Name};
 use syntax::node_id::{NodeId, NodeMap, NodeSet};
 
-use smallvec;
 use std::cell::RefCell;
 use std::cmp::{self, Ordering};
 use std::fmt;
@@ -1348,7 +1347,7 @@ pub trait ToPredicate<'tcx> {
 impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
         ty::Predicate::Trait(
-            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value }),
             self.constness,
         )
     }
@@ -2647,9 +2646,7 @@ impl<'tcx> ::std::ops::Deref for Attributes<'tcx> {
 pub enum ImplOverlapKind {
     /// These impls are always allowed to overlap.
     Permitted {
-        /// Whether or not the impl is permitted due to the trait being
-        /// a marker trait (a trait with #[marker], or a trait with
-        /// no associated items and #![feature(overlapping_marker_traits)] enabled)
+        /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
         marker: bool,
     },
     /// These impls are allowed to overlap, but that raises
@@ -2746,19 +2743,6 @@ impl<'tcx> TyCtxt<'tcx> {
         variant.fields.iter().position(|field| self.hygienic_eq(ident, field.ident, variant.def_id))
     }
 
-    pub fn associated_items(self, def_id: DefId) -> AssocItemsIterator<'tcx> {
-        // Ideally, we would use `-> impl Iterator` here, but it falls
-        // afoul of the conservative "capture [restrictions]" we put
-        // in place, so we use a hand-written iterator.
-        //
-        // [restrictions]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
-        AssocItemsIterator {
-            tcx: self,
-            def_ids: self.associated_item_def_ids(def_id),
-            next_index: 0,
-        }
-    }
-
     /// Returns `true` if the impls are the same polarity and the trait either
     /// has no items or is annotated #[marker] and prevents item overrides.
     pub fn impls_are_allowed_to_overlap(
@@ -2796,15 +2780,7 @@ impl<'tcx> TyCtxt<'tcx> {
             | (ImplPolarity::Negative, ImplPolarity::Negative) => {}
         };
 
-        let is_marker_overlap = if self.features().overlapping_marker_traits {
-            let trait1_is_empty = self.impl_trait_ref(def_id1).map_or(false, |trait_ref| {
-                self.associated_item_def_ids(trait_ref.def_id).is_empty()
-            });
-            let trait2_is_empty = self.impl_trait_ref(def_id2).map_or(false, |trait_ref| {
-                self.associated_item_def_ids(trait_ref.def_id).is_empty()
-            });
-            trait1_is_empty && trait2_is_empty
-        } else {
+        let is_marker_overlap = {
             let is_marker_impl = |def_id: DefId| -> bool {
                 let trait_ref = self.impl_trait_ref(def_id);
                 trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
@@ -2998,20 +2974,22 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-#[derive(Clone)]
+#[derive(Copy, Clone, HashStable)]
 pub struct AssocItemsIterator<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    def_ids: &'tcx [DefId],
-    next_index: usize,
+    pub items: &'tcx [AssocItem],
 }
 
-impl Iterator for AssocItemsIterator<'_> {
+impl<'tcx> Iterator for AssocItemsIterator<'tcx> {
     type Item = AssocItem;
 
+    #[inline]
     fn next(&mut self) -> Option<AssocItem> {
-        let def_id = self.def_ids.get(self.next_index)?;
-        self.next_index += 1;
-        Some(self.tcx.associated_item(*def_id))
+        if let Some((first, rest)) = self.items.split_first() {
+            self.items = rest;
+            Some(*first)
+        } else {
+            None
+        }
     }
 }
 
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index e27f2bdb8d2..dab950e23f6 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -14,7 +14,7 @@ use rustc_target::spec::abi;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::node_id::NodeMap;
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
 
 use log::debug;
 use smallvec::{smallvec, SmallVec};
@@ -81,25 +81,23 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
         }
     }
 
-    fn visit_trait_item(&mut self, item: &'a AssocItem) {
-        self.lctx.with_hir_id_owner(item.id, |lctx| {
-            let hir_item = lctx.lower_trait_item(item);
-            let id = hir::TraitItemId { hir_id: hir_item.hir_id };
-            lctx.trait_items.insert(id, hir_item);
-            lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
+    fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
+        self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
+            AssocCtxt::Trait => {
+                let hir_item = lctx.lower_trait_item(item);
+                let id = hir::TraitItemId { hir_id: hir_item.hir_id };
+                lctx.trait_items.insert(id, hir_item);
+                lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
+            }
+            AssocCtxt::Impl => {
+                let hir_item = lctx.lower_impl_item(item);
+                let id = hir::ImplItemId { hir_id: hir_item.hir_id };
+                lctx.impl_items.insert(id, hir_item);
+                lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
+            }
         });
 
-        visit::walk_trait_item(self, item);
-    }
-
-    fn visit_impl_item(&mut self, item: &'a AssocItem) {
-        self.lctx.with_hir_id_owner(item.id, |lctx| {
-            let hir_item = lctx.lower_impl_item(item);
-            let id = hir::ImplItemId { hir_id: hir_item.hir_id };
-            lctx.impl_items.insert(id, hir_item);
-            lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
-        });
-        visit::walk_impl_item(self, item);
+        visit::walk_assoc_item(self, item, ctxt);
     }
 }
 
@@ -299,20 +297,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
                     // declaration (decl), not the return types.
+                    let asyncness = header.asyncness.node;
                     let body_id =
-                        this.lower_maybe_async_body(span, &decl, header.asyncness.node, Some(body));
+                        this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref());
 
                     let (generics, decl) = this.add_in_band_defs(
                         generics,
                         fn_def_id,
                         AnonymousLifetimeMode::PassThrough,
                         |this, idty| {
-                            this.lower_fn_decl(
-                                &decl,
-                                Some((fn_def_id, idty)),
-                                true,
-                                header.asyncness.node.opt_return_id(),
-                            )
+                            let ret_id = asyncness.opt_return_id();
+                            this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id)
                         },
                     );
                     let sig = hir::FnSig { decl, header: this.lower_fn_header(header) };
@@ -658,7 +653,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
             kind: match i.kind {
-                ForeignItemKind::Fn(ref fdec, ref generics) => {
+                ForeignItemKind::Fn(ref sig, ref generics, _) => {
+                    let fdec = &sig.decl;
                     let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
                         generics,
                         def_id,
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index c3e96a31e40..5816a64fca5 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -32,6 +32,7 @@
 
 #![feature(array_value_iter)]
 #![feature(crate_visibility_modifier)]
+#![recursion_limit = "256"]
 
 use rustc::arena::Arena;
 use rustc::dep_graph::DepGraph;
@@ -63,7 +64,7 @@ use syntax::attr;
 use syntax::node_id::NodeMap;
 use syntax::token::{self, Nonterminal, Token};
 use syntax::tokenstream::{TokenStream, TokenTree};
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
 use syntax::walk_list;
 
 use log::{debug, trace};
@@ -485,25 +486,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 });
             }
 
-            fn visit_trait_item(&mut self, item: &'tcx AssocItem) {
+            fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
                 self.lctx.allocate_hir_id_counter(item.id);
-
-                match item.kind {
-                    AssocItemKind::Fn(_, None) => {
-                        // Ignore patterns in trait methods without bodies
-                        self.with_hir_id_owner(None, |this| visit::walk_trait_item(this, item));
-                    }
-                    _ => self.with_hir_id_owner(Some(item.id), |this| {
-                        visit::walk_trait_item(this, item);
-                    }),
-                }
-            }
-
-            fn visit_impl_item(&mut self, item: &'tcx AssocItem) {
-                self.lctx.allocate_hir_id_counter(item.id);
-                self.with_hir_id_owner(Some(item.id), |this| {
-                    visit::walk_impl_item(this, item);
-                });
+                let owner = match (&item.kind, ctxt) {
+                    // Ignore patterns in trait methods without bodies.
+                    (AssocItemKind::Fn(_, None), AssocCtxt::Trait) => None,
+                    _ => Some(item.id),
+                };
+                self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt));
             }
 
             fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index cb64e2e95bf..79ed7f234f7 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -8,7 +8,7 @@
 
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{struct_span_err, Applicability, FatalError};
+use rustc_errors::{error_code, struct_span_err, Applicability, FatalError};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
 use rustc_session::lint::LintBuffer;
@@ -20,7 +20,7 @@ use std::mem;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::expand::is_proc_macro_attr;
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use syntax::walk_list;
 
 /// Is `self` allowed semantically as the first parameter in an `FnDecl`?
@@ -49,6 +49,13 @@ impl BoundContext {
 
 struct AstValidator<'a> {
     session: &'a Session,
+
+    /// The span of the `extern` in an `extern { ... }` block, if any.
+    extern_mod: Option<&'a Item>,
+
+    /// Are we inside a trait impl?
+    in_trait_impl: bool,
+
     has_proc_macro_decls: bool,
 
     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
@@ -74,6 +81,12 @@ struct AstValidator<'a> {
 }
 
 impl<'a> AstValidator<'a> {
+    fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.in_trait_impl, is_in);
+        f(self);
+        self.in_trait_impl = old;
+    }
+
     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.is_impl_trait_banned, true);
         f(self);
@@ -389,13 +402,9 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
-        if body.is_some() {
-            return;
-        }
-
+    fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
         self.err_handler()
-            .struct_span_err(sp, &format!("associated {} in `impl` without body", ctx))
+            .struct_span_err(sp, msg)
             .span_suggestion(
                 self.session.source_map().end_point(sp),
                 &format!("provide a definition for the {}", ctx),
@@ -405,6 +414,13 @@ impl<'a> AstValidator<'a> {
             .emit();
     }
 
+    fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
+        if body.is_none() {
+            let msg = format!("associated {} in `impl` without body", ctx);
+            self.error_item_without_body(sp, ctx, &msg, sugg);
+        }
+    }
+
     fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
         let span = match bounds {
             [] => return,
@@ -416,8 +432,71 @@ impl<'a> AstValidator<'a> {
             .emit();
     }
 
-    fn check_c_varadic_type(&self, decl: &FnDecl) {
-        for Param { ty, span, .. } in &decl.inputs {
+    /// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
+    fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
+        let body = match body {
+            None => return,
+            Some(body) => body,
+        };
+        self.err_handler()
+            .struct_span_err(ident.span, "incorrect function inside `extern` block")
+            .span_label(ident.span, "cannot have a body")
+            .span_suggestion(
+                body.span,
+                "remove the invalid body",
+                ";".to_string(),
+                Applicability::MaybeIncorrect,
+            )
+            .help(
+                "you might have meant to write a function accessible through FFI, \
+                which can be done by writing `extern fn` outside of the `extern` block",
+            )
+            .span_label(
+                self.current_extern_span(),
+                "`extern` blocks define existing foreign functions and functions \
+                inside of them cannot have a body",
+            )
+            .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
+            .emit();
+    }
+
+    fn current_extern_span(&self) -> Span {
+        self.session.source_map().def_span(self.extern_mod.unwrap().span)
+    }
+
+    /// An `fn` in `extern { ... }` cannot have qualfiers, e.g. `async fn`.
+    fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
+        if header.has_qualifiers() {
+            self.err_handler()
+                .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
+                .span_label(self.current_extern_span(), "in this `extern` block")
+                .span_suggestion(
+                    span.until(ident.span.shrink_to_lo()),
+                    "remove the qualifiers",
+                    "fn ".to_string(),
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
+        }
+    }
+
+    /// Reject C-varadic type unless the function is foreign,
+    /// or free and `unsafe extern "C"` semantically.
+    fn check_c_varadic_type(&self, fk: FnKind<'a>) {
+        match (fk.ctxt(), fk.header()) {
+            (Some(FnCtxt::Foreign), _) => return,
+            (Some(FnCtxt::Free), Some(header)) => match header.ext {
+                Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
+                    if header.unsafety == Unsafety::Unsafe =>
+                {
+                    return;
+                }
+                _ => {}
+            },
+            _ => {}
+        };
+
+        for Param { ty, span, .. } in &fk.decl().inputs {
             if let TyKind::CVarArgs = ty.kind {
                 self.err_handler()
                     .struct_span_err(
@@ -428,6 +507,24 @@ impl<'a> AstValidator<'a> {
             }
         }
     }
+
+    /// We currently do not permit const generics in `const fn`,
+    /// as this is tantamount to allowing compile-time dependent typing.
+    ///
+    /// FIXME(const_generics): Is this really true / necessary? Discuss with @varkor.
+    /// At any rate, the restriction feels too syntactic. Consider moving it to e.g. typeck.
+    fn check_const_fn_const_generic(&self, span: Span, sig: &FnSig, generics: &Generics) {
+        if sig.header.constness.node == Constness::Const {
+            // Look for const generics and error if we find any.
+            for param in &generics.params {
+                if let GenericParamKind::Const { .. } = param.kind {
+                    self.err_handler()
+                        .struct_span_err(span, "const parameters are not permitted in `const fn`")
+                        .emit();
+                }
+            }
+        }
+    }
 }
 
 enum GenericPosition {
@@ -532,9 +629,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
     fn visit_expr(&mut self, expr: &'a Expr) {
         match &expr.kind {
-            ExprKind::Closure(_, _, _, fn_decl, _, _) => {
-                self.check_fn_decl(fn_decl, SelfSemantic::No);
-            }
             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
                 struct_span_err!(
                     self.session,
@@ -647,31 +741,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 generics: _,
                 of_trait: Some(_),
                 ref self_ty,
-                ref items,
+                items: _,
             } => {
-                self.invalid_visibility(&item.vis, None);
-                if let TyKind::Err = self_ty.kind {
-                    self.err_handler()
-                        .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
-                        .help("use `auto trait Trait {}` instead")
+                self.with_in_trait_impl(true, |this| {
+                    this.invalid_visibility(&item.vis, None);
+                    if let TyKind::Err = self_ty.kind {
+                        this.err_handler()
+                            .struct_span_err(
+                                item.span,
+                                "`impl Trait for .. {}` is an obsolete syntax",
+                            )
+                            .help("use `auto trait Trait {}` instead")
+                            .emit();
+                    }
+                    if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
+                        struct_span_err!(
+                            this.session,
+                            item.span,
+                            E0198,
+                            "negative impls cannot be unsafe"
+                        )
                         .emit();
-                }
-                if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
-                    struct_span_err!(
-                        self.session,
-                        item.span,
-                        E0198,
-                        "negative impls cannot be unsafe"
-                    )
-                    .emit();
-                }
-                for impl_item in items {
-                    self.invalid_visibility(&impl_item.vis, None);
-                    if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
-                        self.check_trait_fn_not_const(sig.header.constness);
-                        self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
                     }
-                }
+
+                    visit::walk_item(this, item);
+                });
+                return; // Avoid visiting again.
             }
             ItemKind::Impl {
                 unsafety,
@@ -712,40 +807,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .emit();
                 }
             }
-            ItemKind::Fn(ref sig, ref generics, _) => {
-                self.visit_fn_header(&sig.header);
-                self.check_fn_decl(&sig.decl, SelfSemantic::No);
-                // We currently do not permit const generics in `const fn`, as
-                // this is tantamount to allowing compile-time dependent typing.
-                if sig.header.constness.node == Constness::Const {
-                    // Look for const generics and error if we find any.
-                    for param in &generics.params {
-                        match param.kind {
-                            GenericParamKind::Const { .. } => {
-                                self.err_handler()
-                                    .struct_span_err(
-                                        item.span,
-                                        "const parameters are not permitted in `const fn`",
-                                    )
-                                    .emit();
-                            }
-                            _ => {}
-                        }
-                    }
-                }
-                // Reject C-varadic type unless the function is `unsafe extern "C"` semantically.
-                match sig.header.ext {
-                    Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. })
-                    | Extern::Implicit
-                        if sig.header.unsafety == Unsafety::Unsafe => {}
-                    _ => self.check_c_varadic_type(&sig.decl),
+            ItemKind::Fn(ref sig, ref generics, ref body) => {
+                self.check_const_fn_const_generic(item.span, sig, generics);
+
+                if body.is_none() {
+                    let msg = "free function without a body";
+                    self.error_item_without_body(item.span, "function", msg, " { <body> }");
                 }
             }
-            ItemKind::ForeignMod(..) => {
+            ItemKind::ForeignMod(_) => {
+                let old_item = mem::replace(&mut self.extern_mod, Some(item));
                 self.invalid_visibility(
                     &item.vis,
                     Some("place qualifiers on individual foreign items instead"),
                 );
+                visit::walk_item(self, item);
+                self.extern_mod = old_item;
+                return; // Avoid visiting again.
             }
             ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
@@ -796,7 +874,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.with_bound_context(BoundContext::TraitBounds, |this| {
                     walk_list!(this, visit_param_bound, bounds);
                 });
-                walk_list!(self, visit_trait_item, trait_items);
+                walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return;
             }
@@ -820,19 +898,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
-        match fi.kind {
-            ForeignItemKind::Fn(ref decl, _) => {
-                self.check_fn_decl(decl, SelfSemantic::No);
-                Self::check_decl_no_pat(decl, |span, _| {
-                    struct_span_err!(
-                        self.session,
-                        span,
-                        E0130,
-                        "patterns aren't allowed in foreign function declarations"
-                    )
-                    .span_label(span, "pattern not allowed in foreign function")
-                    .emit();
-                });
+        match &fi.kind {
+            ForeignItemKind::Fn(sig, _, body) => {
+                self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
+                self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
             }
             ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
         }
@@ -1011,67 +1080,84 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         })
     }
 
-    fn visit_impl_item(&mut self, ii: &'a AssocItem) {
-        match &ii.kind {
-            AssocItemKind::Const(_, body) => {
-                self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
-            }
-            AssocItemKind::Fn(_, body) => {
-                self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
-            }
-            AssocItemKind::TyAlias(bounds, body) => {
-                self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
-                self.check_impl_assoc_type_no_bounds(bounds);
-            }
-            _ => {}
+    fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
+        // Only associated `fn`s can have `self` parameters.
+        let self_semantic = match fk.ctxt() {
+            Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
+            _ => SelfSemantic::No,
+        };
+        self.check_fn_decl(fk.decl(), self_semantic);
+
+        self.check_c_varadic_type(fk);
+
+        // Functions without bodies cannot have patterns.
+        if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
+            Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
+                let (code, msg, label) = match ctxt {
+                    FnCtxt::Foreign => (
+                        error_code!(E0130),
+                        "patterns aren't allowed in foreign function declarations",
+                        "pattern not allowed in foreign function",
+                    ),
+                    _ => (
+                        error_code!(E0642),
+                        "patterns aren't allowed in functions without bodies",
+                        "pattern not allowed in function without body",
+                    ),
+                };
+                if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
+                    self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
+                } else {
+                    self.err_handler()
+                        .struct_span_err(span, msg)
+                        .span_label(span, label)
+                        .code(code)
+                        .emit();
+                }
+            });
         }
-        visit::walk_impl_item(self, ii);
+
+        visit::walk_fn(self, fk, span);
     }
 
-    fn visit_trait_item(&mut self, ti: &'a AssocItem) {
-        self.invalid_visibility(&ti.vis, None);
-        self.check_defaultness(ti.span, ti.defaultness);
-
-        if let AssocItemKind::Fn(sig, block) = &ti.kind {
-            self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node);
-            self.check_trait_fn_not_const(sig.header.constness);
-            if block.is_none() {
-                Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
-                    if mut_ident {
-                        self.lint_buffer.buffer_lint(
-                            PATTERNS_IN_FNS_WITHOUT_BODY,
-                            ti.id,
-                            span,
-                            "patterns aren't allowed in methods without bodies",
-                        );
-                    } else {
-                        struct_span_err!(
-                            self.session,
-                            span,
-                            E0642,
-                            "patterns aren't allowed in methods without bodies"
-                        )
-                        .emit();
-                    }
-                });
-            }
+    fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
+        if ctxt == AssocCtxt::Trait {
+            self.check_defaultness(item.span, item.defaultness);
         }
 
-        visit::walk_trait_item(self, ti);
-    }
+        if ctxt == AssocCtxt::Impl {
+            match &item.kind {
+                AssocItemKind::Const(_, body) => {
+                    self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
+                }
+                AssocItemKind::Fn(_, body) => {
+                    self.check_impl_item_provided(item.span, body, "function", " { <body> }");
+                }
+                AssocItemKind::TyAlias(bounds, body) => {
+                    self.check_impl_item_provided(item.span, body, "type", " = <type>;");
+                    self.check_impl_assoc_type_no_bounds(bounds);
+                }
+                _ => {}
+            }
+        }
 
-    fn visit_assoc_item(&mut self, item: &'a AssocItem) {
-        if let AssocItemKind::Fn(sig, _) = &item.kind {
-            self.check_fn_decl(&sig.decl, SelfSemantic::Yes);
-            self.check_c_varadic_type(&sig.decl);
+        if ctxt == AssocCtxt::Trait || self.in_trait_impl {
+            self.invalid_visibility(&item.vis, None);
+            if let AssocItemKind::Fn(sig, _) = &item.kind {
+                self.check_trait_fn_not_const(sig.header.constness);
+                self.check_trait_fn_not_async(item.span, sig.header.asyncness.node);
+            }
         }
-        visit::walk_assoc_item(self, item);
+
+        self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
     }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
     let mut validator = AstValidator {
         session,
+        extern_mod: None,
+        in_trait_impl: false,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
         bound_context: None,
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 3b13ab354fd..a10ac94d894 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -8,7 +8,7 @@ use rustc_span::Span;
 use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
 use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
 use syntax::attr;
-use syntax::visit::{self, FnKind, Visitor};
+use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 
 use log::debug;
 
@@ -492,25 +492,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_pat(self, pattern)
     }
 
-    fn visit_fn(
-        &mut self,
-        fn_kind: FnKind<'a>,
-        fn_decl: &'a ast::FnDecl,
-        span: Span,
-        _node_id: NodeId,
-    ) {
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
-            // Stability of const fn methods are covered in
-            // `visit_trait_item` and `visit_impl_item` below; this is
-            // because default methods don't pass through this point.
+            // Stability of const fn methods are covered in `visit_assoc_item` below.
             self.check_extern(header.ext);
         }
 
-        if fn_decl.c_variadic() {
+        if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
             gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
         }
 
-        visit::walk_fn(self, fn_kind, fn_decl, span)
+        visit::walk_fn(self, fn_kind, span)
     }
 
     fn visit_generic_param(&mut self, param: &'a GenericParam) {
@@ -539,56 +531,35 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_assoc_ty_constraint(self, constraint)
     }
 
-    fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) {
-        match ti.kind {
-            ast::AssocItemKind::Fn(ref sig, ref block) => {
-                if block.is_none() {
-                    self.check_extern(sig.header.ext);
-                }
-                if sig.header.constness.node == ast::Constness::Const {
-                    gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
+    fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
+        if i.defaultness == ast::Defaultness::Default {
+            gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
+        }
+
+        match i.kind {
+            ast::AssocItemKind::Fn(ref sig, _) => {
+                let constness = sig.header.constness.node;
+                if let (ast::Constness::Const, AssocCtxt::Trait) = (constness, ctxt) {
+                    gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
                 }
             }
-            ast::AssocItemKind::TyAlias(_, ref default) => {
-                if let Some(_) = default {
+            ast::AssocItemKind::TyAlias(_, ref ty) => {
+                if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
                     gate_feature_post!(
                         &self,
                         associated_type_defaults,
-                        ti.span,
+                        i.span,
                         "associated type defaults are unstable"
                     );
                 }
-            }
-            _ => {}
-        }
-        visit::walk_trait_item(self, ti)
-    }
-
-    fn visit_assoc_item(&mut self, ii: &'a ast::AssocItem) {
-        if ii.defaultness == ast::Defaultness::Default {
-            gate_feature_post!(&self, specialization, ii.span, "specialization is unstable");
-        }
-
-        match ii.kind {
-            ast::AssocItemKind::Fn(ref sig, _) => {
-                if sig.decl.c_variadic() {
-                    gate_feature_post!(
-                        &self,
-                        c_variadic,
-                        ii.span,
-                        "C-variadic functions are unstable"
-                    );
-                }
-            }
-            ast::AssocItemKind::TyAlias(_, ref ty) => {
                 if let Some(ty) = ty {
                     self.check_impl_trait(ty);
                 }
-                self.check_gat(&ii.generics, ii.span);
+                self.check_gat(&i.generics, i.span);
             }
             _ => {}
         }
-        visit::walk_assoc_item(self, ii)
+        visit::walk_assoc_item(self, i, ctxt)
     }
 
     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs
index 9fe7238fcfc..ed1ccdf6a76 100644
--- a/src/librustc_ast_passes/node_count.rs
+++ b/src/librustc_ast_passes/node_count.rs
@@ -67,13 +67,13 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_generics(self, g)
     }
-    fn visit_fn(&mut self, fk: FnKind<'_>, fd: &FnDecl, s: Span, _: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'_>, s: Span, _: NodeId) {
         self.count += 1;
-        walk_fn(self, fk, fd, s)
+        walk_fn(self, fk, s)
     }
-    fn visit_assoc_item(&mut self, ti: &AssocItem) {
+    fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) {
         self.count += 1;
-        walk_assoc_item(self, ti)
+        walk_assoc_item(self, ti, ctxt);
     }
     fn visit_trait_ref(&mut self, t: &TraitRef) {
         self.count += 1;
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 3cc67a7c821..d9077d1606f 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1020,18 +1020,8 @@ impl<'a> State<'a> {
         self.maybe_print_comment(item.span.lo());
         self.print_outer_attributes(&item.attrs);
         match item.kind {
-            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
-                self.head("");
-                self.print_fn(
-                    decl,
-                    ast::FnHeader::default(),
-                    Some(item.ident),
-                    generics,
-                    &item.vis,
-                );
-                self.end(); // end head-ibox
-                self.s.word(";");
-                self.end(); // end the outer fn box
+            ast::ForeignItemKind::Fn(ref sig, ref gen, ref body) => {
+                self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
             }
             ast::ForeignItemKind::Static(ref t, m) => {
                 self.head(visibility_qualified(&item.vis, "static"));
@@ -1154,11 +1144,8 @@ impl<'a> State<'a> {
                 self.s.word(";");
                 self.end(); // end the outer cbox
             }
-            ast::ItemKind::Fn(ref sig, ref param_names, ref body) => {
-                self.head("");
-                self.print_fn(&sig.decl, sig.header, Some(item.ident), param_names, &item.vis);
-                self.s.word(" ");
-                self.print_block_with_attrs(body, &item.attrs);
+            ast::ItemKind::Fn(ref sig, ref gen, ref body) => {
+                self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
             }
             ast::ItemKind::Mod(ref _mod) => {
                 self.head(visibility_qualified(&item.vis, "mod"));
@@ -1483,16 +1470,8 @@ impl<'a> State<'a> {
                 self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis);
             }
             ast::AssocItemKind::Fn(sig, body) => {
-                if body.is_some() {
-                    self.head("");
-                }
-                self.print_fn(&sig.decl, sig.header, Some(item.ident), &item.generics, &item.vis);
-                if let Some(body) = body {
-                    self.nbsp();
-                    self.print_block_with_attrs(body, &item.attrs);
-                } else {
-                    self.s.word(";");
-                }
+                let body = body.as_deref();
+                self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs);
             }
             ast::AssocItemKind::TyAlias(bounds, ty) => {
                 self.print_associated_type(item.ident, bounds, ty.as_deref());
@@ -2412,6 +2391,27 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_fn_full(
+        &mut self,
+        sig: &ast::FnSig,
+        name: ast::Ident,
+        generics: &ast::Generics,
+        vis: &ast::Visibility,
+        body: Option<&ast::Block>,
+        attrs: &[ast::Attribute],
+    ) {
+        if body.is_some() {
+            self.head("");
+        }
+        self.print_fn(&sig.decl, sig.header, Some(name), generics, vis);
+        if let Some(body) = body {
+            self.nbsp();
+            self.print_block_with_attrs(body, attrs);
+        } else {
+            self.s.word(";");
+        }
+    }
+
     crate fn print_fn(
         &mut self,
         decl: &ast::FnDecl,
@@ -2698,13 +2698,9 @@ impl<'a> State<'a> {
             where_clause: ast::WhereClause { predicates: Vec::new(), span: rustc_span::DUMMY_SP },
             span: rustc_span::DUMMY_SP,
         };
-        self.print_fn(
-            decl,
-            ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() },
-            name,
-            &generics,
-            &dummy_spanned(ast::VisibilityKind::Inherited),
-        );
+        let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
+        let vis = dummy_spanned(ast::VisibilityKind::Inherited);
+        self.print_fn(decl, header, name, &generics, &vis);
         self.end();
     }
 
diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs
index 957d34b7d89..ec0d55b38a7 100644
--- a/src/librustc_builtin_macros/global_allocator.rs
+++ b/src/librustc_builtin_macros/global_allocator.rs
@@ -66,7 +66,7 @@ impl AllocFnFactory<'_, '_> {
         let decl = self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty));
         let header = FnHeader { unsafety: Unsafety::Unsafe, ..FnHeader::default() };
         let sig = FnSig { decl, header };
-        let kind = ItemKind::Fn(sig, Generics::default(), self.cx.block_expr(output_expr));
+        let kind = ItemKind::Fn(sig, Generics::default(), Some(self.cx.block_expr(output_expr)));
         let item = self.cx.item(
             self.span,
             self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
diff --git a/src/librustc_builtin_macros/log_syntax.rs b/src/librustc_builtin_macros/log_syntax.rs
index 6d9bfbfd05f..ac7ba49ba18 100644
--- a/src/librustc_builtin_macros/log_syntax.rs
+++ b/src/librustc_builtin_macros/log_syntax.rs
@@ -1,6 +1,5 @@
 use rustc_ast_pretty::pprust;
 use rustc_expand::base;
-use rustc_span;
 use syntax::tokenstream::TokenStream;
 
 pub fn expand_log_syntax<'cx>(
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index 6a73f121c99..70f1c0e4e2d 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -307,7 +307,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let decl = ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default() };
-    let main = ast::ItemKind::Fn(sig, ast::Generics::default(), main_body);
+    let main = ast::ItemKind::Fn(sig, ast::Generics::default(), Some(main_body));
 
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 3a14fa5ae31..4f05aac0898 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -968,7 +968,78 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary
     }
 }
 
+// Because windows-gnu target is meant to be self-contained for pure Rust code it bundles
+// own mingw-w64 libraries. These libraries are usually not compatible with mingw-w64
+// installed in the system. This breaks many cases where Rust is mixed with other languages
+// (e.g. *-sys crates).
+// We prefer system mingw-w64 libraries if they are available to avoid this issue.
+fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
+    fn find_exe_in_path<P>(exe_name: P) -> Option<PathBuf>
+    where
+        P: AsRef<Path>,
+    {
+        for dir in env::split_paths(&env::var_os("PATH")?) {
+            let full_path = dir.join(&exe_name);
+            if full_path.is_file() {
+                return Some(fix_windows_verbatim_for_gcc(&full_path));
+            }
+        }
+        None
+    }
+
+    fn probe(sess: &Session) -> Option<PathBuf> {
+        if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) {
+            let linker_path = if cfg!(windows) && linker.extension().is_none() {
+                linker.with_extension("exe")
+            } else {
+                linker
+            };
+            if let Some(linker_path) = find_exe_in_path(linker_path) {
+                let mingw_arch = match &sess.target.target.arch {
+                    x if x == "x86" => "i686",
+                    x => x,
+                };
+                let mingw_dir = format!("{}-w64-mingw32", mingw_arch);
+                // Here we have path/bin/gcc but we need path/
+                let mut path = linker_path;
+                path.pop();
+                path.pop();
+                // Based on Clang MinGW driver
+                let probe_path = path.join(&mingw_dir).join("lib");
+                if probe_path.exists() {
+                    return Some(probe_path);
+                };
+                let probe_path = path.join(&mingw_dir).join("sys-root/mingw/lib");
+                if probe_path.exists() {
+                    return Some(probe_path);
+                };
+            };
+        };
+        None
+    }
+
+    let mut system_library_path = sess.system_library_path.borrow_mut();
+    match &*system_library_path {
+        Some(Some(compiler_libs_path)) => Some(compiler_libs_path.clone()),
+        Some(None) => None,
+        None => {
+            let path = probe(sess);
+            *system_library_path = Some(path.clone());
+            path
+        }
+    }
+}
+
 pub fn get_file_path(sess: &Session, name: &str) -> PathBuf {
+    // prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
+    if sess.target.target.llvm_target.contains("windows-gnu") {
+        if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
+            let file_path = compiler_libs_path.join(name);
+            if file_path.exists() {
+                return file_path;
+            }
+        }
+    }
     let fs = sess.target_filesearch(PathKind::Native);
     let file_path = fs.get_lib_path().join(name);
     if file_path.exists() {
@@ -1150,6 +1221,13 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
     // target descriptor
     let t = &sess.target.target;
 
+    // prefer system mingw-w64 libs, see get_crt_libs_path comment for more details
+    if cfg!(windows) && sess.target.target.llvm_target.contains("windows-gnu") {
+        if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
+            cmd.include_path(&compiler_libs_path);
+        }
+    }
+
     cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
 
     for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 974d9dcfae4..0384776e9fb 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -74,7 +74,7 @@
 
 use crate::fx::{FxHashMap, FxHashSet};
 
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
 use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash;
@@ -146,7 +146,7 @@ pub struct ObligationForest<O: ForestObligation> {
     active_cache: FxHashMap<O::Predicate, usize>,
 
     /// A vector reused in compress(), to avoid allocating new vectors.
-    node_rewrites: RefCell<Vec<usize>>,
+    node_rewrites: Vec<usize>,
 
     obligation_tree_id_generator: ObligationTreeIdGenerator,
 
@@ -285,7 +285,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             nodes: vec![],
             done_cache: Default::default(),
             active_cache: Default::default(),
-            node_rewrites: RefCell::new(vec![]),
+            node_rewrites: vec![],
             obligation_tree_id_generator: (0..).map(ObligationTreeId),
             error_cache: Default::default(),
         }
@@ -590,7 +590,7 @@ impl<O: ForestObligation> ObligationForest<O> {
     #[inline(never)]
     fn compress(&mut self, do_completed: DoCompleted) -> Option<Vec<O>> {
         let orig_nodes_len = self.nodes.len();
-        let mut node_rewrites: Vec<_> = self.node_rewrites.replace(vec![]);
+        let mut node_rewrites: Vec<_> = std::mem::take(&mut self.node_rewrites);
         debug_assert!(node_rewrites.is_empty());
         node_rewrites.extend(0..orig_nodes_len);
         let mut dead_nodes = 0;
@@ -651,7 +651,7 @@ impl<O: ForestObligation> ObligationForest<O> {
         }
 
         node_rewrites.truncate(0);
-        self.node_rewrites.replace(node_rewrites);
+        self.node_rewrites = node_rewrites;
 
         if do_completed == DoCompleted::Yes { Some(removed_done_obligations) } else { None }
     }
diff --git a/src/librustc_error_codes/error_codes/E0264.md b/src/librustc_error_codes/error_codes/E0264.md
index e1e7516cec2..708eac8837a 100644
--- a/src/librustc_error_codes/error_codes/E0264.md
+++ b/src/librustc_error_codes/error_codes/E0264.md
@@ -1,4 +1,6 @@
-An unknown external lang item was used. Erroneous code example:
+An unknown external lang item was used.
+
+Erroneous code example:
 
 ```compile_fail,E0264
 #![feature(lang_items)]
diff --git a/src/librustc_error_codes/error_codes/E0267.md b/src/librustc_error_codes/error_codes/E0267.md
index 066ebee0ffb..951490df874 100644
--- a/src/librustc_error_codes/error_codes/E0267.md
+++ b/src/librustc_error_codes/error_codes/E0267.md
@@ -1,5 +1,7 @@
-This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Erroneous code example:
+A loop keyword (`break` or `continue`) was used inside a closure but outside of
+any loop.
+
+Erroneous code example:
 
 ```compile_fail,E0267
 let w = || { break; }; // error: `break` inside of a closure
diff --git a/src/librustc_error_codes/error_codes/E0268.md b/src/librustc_error_codes/error_codes/E0268.md
index 7f3ac118601..436aef79fe0 100644
--- a/src/librustc_error_codes/error_codes/E0268.md
+++ b/src/librustc_error_codes/error_codes/E0268.md
@@ -1,6 +1,6 @@
-This error indicates the use of a loop keyword (`break` or `continue`) outside
-of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken. Erroneous code example:
+A loop keyword (`break` or `continue`) was used outside of a loop.
+
+Erroneous code example:
 
 ```compile_fail,E0268
 fn some_func() {
@@ -8,6 +8,7 @@ fn some_func() {
 }
 ```
 
+Without a loop to break out of or continue in, no sensible action can be taken.
 Please verify that you are using `break` and `continue` only in loops. Example:
 
 ```
diff --git a/src/librustc_error_codes/error_codes/E0454.md b/src/librustc_error_codes/error_codes/E0454.md
index d3314885081..80eb91e43d1 100644
--- a/src/librustc_error_codes/error_codes/E0454.md
+++ b/src/librustc_error_codes/error_codes/E0454.md
@@ -1,6 +1,6 @@
 A link name was given with an empty name. Erroneous code example:
 
-```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen)
+```compile_fail,E0454
 #[link(name = "")] extern {}
 // error: `#[link(name = "")]` given with empty name
 ```
diff --git a/src/librustc_error_codes/error_codes/E0458.md b/src/librustc_error_codes/error_codes/E0458.md
index 385079d403d..5996f190b34 100644
--- a/src/librustc_error_codes/error_codes/E0458.md
+++ b/src/librustc_error_codes/error_codes/E0458.md
@@ -1,6 +1,6 @@
 An unknown "kind" was specified for a link attribute. Erroneous code example:
 
-```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen)
+```compile_fail,E0458
 #[link(kind = "wonderful_unicorn")] extern {}
 // error: unknown kind: `wonderful_unicorn`
 ```
diff --git a/src/librustc_error_codes/error_codes/E0459.md b/src/librustc_error_codes/error_codes/E0459.md
index 663bc322ee6..580cbf1e1c6 100644
--- a/src/librustc_error_codes/error_codes/E0459.md
+++ b/src/librustc_error_codes/error_codes/E0459.md
@@ -1,6 +1,6 @@
 A link was used without a name parameter. Erroneous code example:
 
-```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen)
+```compile_fail,E0459
 #[link(kind = "dylib")] extern {}
 // error: `#[link(...)]` specified without `name = "foo"`
 ```
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 536259e0547..e167089b93a 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -17,7 +17,7 @@ use syntax::mut_visit::{self, MutVisitor};
 use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::{self, TokenStream};
-use syntax::visit::Visitor;
+use syntax::visit::{AssocCtxt, Visitor};
 
 use std::default::Default;
 use std::iter;
@@ -103,8 +103,8 @@ impl Annotatable {
     pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
         match self {
             Annotatable::Item(item) => visitor.visit_item(item),
-            Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item),
-            Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item),
+            Annotatable::TraitItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Trait),
+            Annotatable::ImplItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Impl),
             Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
             Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
             Annotatable::Expr(expr) => visitor.visit_expr(expr),
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index f08bed57315..90692fe1ec9 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -25,7 +25,7 @@ use syntax::ptr::P;
 use syntax::token;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::util::map_in_place::MapInPlace;
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
 
 use smallvec::{smallvec, SmallVec};
 use std::io::ErrorKind;
@@ -39,7 +39,7 @@ macro_rules! ast_fragments {
         $($Kind:ident($AstTy:ty) {
             $kind_name:expr;
             $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
-            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)?
+            $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*);)?
             fn $make_ast:ident;
         })*
     ) => {
@@ -127,7 +127,7 @@ macro_rules! ast_fragments {
                     AstFragment::OptExpr(None) => {}
                     $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
                     $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
-                        visitor.$visit_ast_elt(ast_elt);
+                        visitor.$visit_ast_elt(ast_elt, $($args)*);
                     })?)*
                 }
             }
@@ -147,52 +147,58 @@ ast_fragments! {
     Pat(P<ast::Pat>) { "pattern"; one fn visit_pat; fn visit_pat; fn make_pat; }
     Ty(P<ast::Ty>) { "type"; one fn visit_ty; fn visit_ty; fn make_ty; }
     Stmts(SmallVec<[ast::Stmt; 1]>) {
-        "statement"; many fn flat_map_stmt; fn visit_stmt; fn make_stmts;
+        "statement"; many fn flat_map_stmt; fn visit_stmt(); fn make_stmts;
     }
     Items(SmallVec<[P<ast::Item>; 1]>) {
-        "item"; many fn flat_map_item; fn visit_item; fn make_items;
+        "item"; many fn flat_map_item; fn visit_item(); fn make_items;
     }
     TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
-        "trait item"; many fn flat_map_trait_item; fn visit_trait_item; fn make_trait_items;
+        "trait item";
+        many fn flat_map_trait_item;
+        fn visit_assoc_item(AssocCtxt::Trait);
+        fn make_trait_items;
     }
     ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
-        "impl item"; many fn flat_map_impl_item; fn visit_impl_item; fn make_impl_items;
+        "impl item";
+        many fn flat_map_impl_item;
+        fn visit_assoc_item(AssocCtxt::Impl);
+        fn make_impl_items;
     }
     ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
         "foreign item";
         many fn flat_map_foreign_item;
-        fn visit_foreign_item;
+        fn visit_foreign_item();
         fn make_foreign_items;
     }
     Arms(SmallVec<[ast::Arm; 1]>) {
-        "match arm"; many fn flat_map_arm; fn visit_arm; fn make_arms;
+        "match arm"; many fn flat_map_arm; fn visit_arm(); fn make_arms;
     }
     Fields(SmallVec<[ast::Field; 1]>) {
-        "field expression"; many fn flat_map_field; fn visit_field; fn make_fields;
+        "field expression"; many fn flat_map_field; fn visit_field(); fn make_fields;
     }
     FieldPats(SmallVec<[ast::FieldPat; 1]>) {
         "field pattern";
         many fn flat_map_field_pattern;
-        fn visit_field_pattern;
+        fn visit_field_pattern();
         fn make_field_patterns;
     }
     GenericParams(SmallVec<[ast::GenericParam; 1]>) {
         "generic parameter";
         many fn flat_map_generic_param;
-        fn visit_generic_param;
+        fn visit_generic_param();
         fn make_generic_params;
     }
     Params(SmallVec<[ast::Param; 1]>) {
-        "function parameter"; many fn flat_map_param; fn visit_param; fn make_params;
+        "function parameter"; many fn flat_map_param; fn visit_param(); fn make_params;
     }
     StructFields(SmallVec<[ast::StructField; 1]>) {
         "field";
         many fn flat_map_struct_field;
-        fn visit_struct_field;
+        fn visit_struct_field();
         fn make_struct_fields;
     }
     Variants(SmallVec<[ast::Variant; 1]>) {
-        "variant"; many fn flat_map_variant; fn visit_variant; fn make_variants;
+        "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
     }
 }
 
@@ -363,7 +369,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 krate.attrs = vec![];
                 krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
             }
-            _ => unreachable!(),
+            Some(ast::Item { span, kind, .. }) => {
+                krate.attrs = vec![];
+                krate.module = ast::Mod { inner: orig_mod_span, items: vec![], inline: true };
+                self.cx.span_err(
+                    span,
+                    &format!(
+                        "expected crate top-level item to be a module after macro expansion, found a {}",
+                        kind.descriptive_variant()
+                    ),
+                );
+            }
         };
         self.cx.trace_macros_diag();
         krate
@@ -599,8 +615,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
             );
             err.help(&format!(
-                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-                suggested_limit
+                "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+                suggested_limit, self.cx.ecfg.crate_name,
             ));
             err.emit();
             self.cx.trace_macros_diag();
@@ -851,7 +867,7 @@ pub fn parse_ast_fragment<'a>(
         AstFragmentKind::ForeignItems => {
             let mut items = SmallVec::new();
             while this.token != token::Eof {
-                items.push(this.parse_foreign_item(DUMMY_SP)?);
+                items.push(this.parse_foreign_item()?);
             }
             AstFragment::ForeignItems(items)
         }
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 0252d88e738..4ae79f9ccaa 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -344,9 +344,6 @@ declare_features! (
     /// Allows `extern "x86-interrupt" fn()`.
     (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
 
-    /// Allows overlapping impls of marker traits.
-    (active, overlapping_marker_traits, "1.18.0", Some(29864), None),
-
     /// Allows a test to fail without failing the whole suite.
     (active, allow_fail, "1.19.0", Some(46488), None),
 
diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs
index d5b6fe81c7b..e6ea093fe89 100644
--- a/src/librustc_feature/removed.rs
+++ b/src/librustc_feature/removed.rs
@@ -108,7 +108,9 @@ declare_features! (
     /// Allows using `#[on_unimplemented(..)]` on traits.
     /// (Moved to `rustc_attrs`.)
     (removed, on_unimplemented, "1.40.0", None, None, None),
-
+    /// Allows overlapping impls of marker traits.
+    (removed, overlapping_marker_traits, "1.42.0", Some(29864), None,
+     Some("removed in favor of `#![feature(marker_trait_attr)]`")),
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 3ed0ad16eeb..0c93a192667 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2260,10 +2260,10 @@ impl TraitRef<'_> {
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct PolyTraitRef<'hir> {
-    /// The `'a` in `<'a> Foo<&'a T>`.
+    /// The `'a` in `for<'a> Foo<&'a T>`.
     pub bound_generic_params: &'hir [GenericParam<'hir>],
 
-    /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
+    /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
     pub trait_ref: TraitRef<'hir>,
 
     pub span: Span,
diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs
index 696a350ebdd..294074cd3e5 100644
--- a/src/librustc_hir/stable_hash_impls.rs
+++ b/src/librustc_hir/stable_hash_impls.rs
@@ -11,9 +11,7 @@ pub trait HashStableContext: syntax::HashStableContext + rustc_target::HashStabl
     fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher);
     fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher);
     fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher);
-    fn hash_item_id(&mut self, _: ItemId, hasher: &mut StableHasher);
-    fn hash_impl_item_id(&mut self, _: ImplItemId, hasher: &mut StableHasher);
-    fn hash_trait_item_id(&mut self, _: TraitItemId, hasher: &mut StableHasher);
+    fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher);
     fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher);
     fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher);
     fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
@@ -38,21 +36,28 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for BodyId {
     }
 }
 
+// The following implementations of HashStable for `ItemId`, `TraitItemId`, and
+// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
+// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
+// are used when another item in the HIR is *referenced* and we certainly
+// want to pick up on a reference changing its target, so we hash the NodeIds
+// in "DefPath Mode".
+
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_item_id(*self, hasher)
+        hcx.hash_reference_to_item(self.id, hasher)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_impl_item_id(*self, hasher)
+        hcx.hash_reference_to_item(self.hir_id, hasher)
     }
 }
 
 impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItemId {
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        hcx.hash_trait_item_id(*self, hasher)
+        hcx.hash_reference_to_item(self.hir_id, hasher)
     }
 }
 
diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs
index 7534b7e9ef4..5c72b049d97 100644
--- a/src/librustc_incremental/persist/file_format.rs
+++ b/src/librustc_incremental/persist/file_format.rs
@@ -90,8 +90,7 @@ pub fn read_file(
         let mut rustc_version_str_len = [0u8; 1];
         file.read_exact(&mut rustc_version_str_len)?;
         let rustc_version_str_len = rustc_version_str_len[0] as usize;
-        let mut buffer = Vec::with_capacity(rustc_version_str_len);
-        buffer.resize(rustc_version_str_len, 0);
+        let mut buffer = vec![0; rustc_version_str_len];
         file.read_exact(&mut buffer)?;
 
         if buffer != rustc_version().as_bytes() {
diff --git a/src/librustc_interface/callbacks.rs b/src/librustc_interface/callbacks.rs
index eb9c118bb01..803e8958572 100644
--- a/src/librustc_interface/callbacks.rs
+++ b/src/librustc_interface/callbacks.rs
@@ -11,7 +11,6 @@
 
 use rustc::ty::tls;
 use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS};
-use rustc_span;
 use std::fmt;
 
 /// This is a callback from libsyntax as it cannot access the implicit state
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 0be73e55e9c..bf8bcd71efa 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -17,7 +17,6 @@ use rustc::traits;
 use rustc::ty::steal::Steal;
 use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc::util::common::ErrorReported;
-use rustc_builtin_macros;
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_codegen_utils::link::filename_for_metadata;
@@ -26,18 +25,15 @@ use rustc_data_structures::{box_region_allow_access, declare_box_region_type, pa
 use rustc_errors::PResult;
 use rustc_expand::base::ExtCtxt;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
-use rustc_incremental;
 use rustc_lint::LintStore;
 use rustc_mir as mir;
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
 use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
-use rustc_privacy;
 use rustc_resolve::{Resolver, ResolverArenas};
 use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
-use rustc_traits;
 use rustc_typeck as typeck;
 use syntax::mut_visit::MutVisitor;
 use syntax::{self, ast, visit};
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 154b1608dcc..ca66717ac5e 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -43,7 +43,7 @@ use rustc_span::{BytePos, Span};
 use syntax::ast::{self, Expr};
 use syntax::attr::{self, HasAttrs};
 use syntax::tokenstream::{TokenStream, TokenTree};
-use syntax::visit::FnKind;
+use syntax::visit::{FnCtxt, FnKind};
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -259,34 +259,22 @@ impl EarlyLintPass for UnsafeCode {
         }
     }
 
-    fn check_fn(
-        &mut self,
-        cx: &EarlyContext<'_>,
-        fk: FnKind<'_>,
-        _: &ast::FnDecl,
-        span: Span,
-        _: ast::NodeId,
-    ) {
-        match fk {
-            FnKind::ItemFn(_, ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, ..) => {
-                self.report_unsafe(cx, span, "declaration of an `unsafe` function")
-            }
-
-            FnKind::Method(_, sig, ..) => {
-                if sig.header.unsafety == ast::Unsafety::Unsafe {
-                    self.report_unsafe(cx, span, "implementation of an `unsafe` method")
-                }
-            }
-
-            _ => (),
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) {
-        if let ast::AssocItemKind::Fn(ref sig, None) = item.kind {
-            if sig.header.unsafety == ast::Unsafety::Unsafe {
-                self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
-            }
+    fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast::NodeId) {
+        if let FnKind::Fn(
+            ctxt,
+            _,
+            ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafety::Unsafe, .. }, .. },
+            _,
+            body,
+        ) = fk
+        {
+            let msg = match ctxt {
+                FnCtxt::Foreign => return,
+                FnCtxt::Free => "declaration of an `unsafe` function",
+                FnCtxt::Assoc(_) if body.is_none() => "declaration of an `unsafe` method",
+                FnCtxt::Assoc(_) => "implementation of an `unsafe` method",
+            };
+            self.report_unsafe(cx, span, msg);
         }
     }
 }
diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs
index 490114b2d4d..542cbea0c95 100644
--- a/src/librustc_lint/early.rs
+++ b/src/librustc_lint/early.rs
@@ -116,17 +116,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         ast_visit::walk_stmt(self, s);
     }
 
-    fn visit_fn(
-        &mut self,
-        fk: ast_visit::FnKind<'a>,
-        decl: &'a ast::FnDecl,
-        span: Span,
-        id: ast::NodeId,
-    ) {
-        run_early_pass!(self, check_fn, fk, decl, span, id);
+    fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
+        run_early_pass!(self, check_fn, fk, span, id);
         self.check_id(id);
-        ast_visit::walk_fn(self, fk, decl, span);
-        run_early_pass!(self, check_fn_post, fk, decl, span, id);
+        ast_visit::walk_fn(self, fk, span);
+        run_early_pass!(self, check_fn_post, fk, span, id);
     }
 
     fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
@@ -213,19 +207,18 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         ast_visit::walk_poly_trait_ref(self, t, m);
     }
 
-    fn visit_trait_item(&mut self, trait_item: &'a ast::AssocItem) {
-        self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
-            run_early_pass!(cx, check_trait_item, trait_item);
-            ast_visit::walk_trait_item(cx, trait_item);
-            run_early_pass!(cx, check_trait_item_post, trait_item);
-        });
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &'a ast::AssocItem) {
-        self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
-            run_early_pass!(cx, check_impl_item, impl_item);
-            ast_visit::walk_impl_item(cx, impl_item);
-            run_early_pass!(cx, check_impl_item_post, impl_item);
+    fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
+        self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
+            ast_visit::AssocCtxt::Trait => {
+                run_early_pass!(cx, check_trait_item, item);
+                ast_visit::walk_assoc_item(cx, item, ctxt);
+                run_early_pass!(cx, check_trait_item_post, item);
+            }
+            ast_visit::AssocCtxt::Impl => {
+                run_early_pass!(cx, check_impl_item, item);
+                ast_visit::walk_assoc_item(cx, item, ctxt);
+                run_early_pass!(cx, check_impl_item_post, item);
+            }
         });
     }
 
diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs
index 7e5d670767a..36de625cafa 100644
--- a/src/librustc_lint/passes.rs
+++ b/src/librustc_lint/passes.rs
@@ -179,10 +179,9 @@ macro_rules! early_lint_methods {
             fn check_where_predicate(a: &ast::WherePredicate);
             fn check_poly_trait_ref(a: &ast::PolyTraitRef,
                                     b: &ast::TraitBoundModifier);
-            fn check_fn(a: syntax::visit::FnKind<'_>, b: &ast::FnDecl, c: Span, d_: ast::NodeId);
+            fn check_fn(a: syntax::visit::FnKind<'_>, c: Span, d_: ast::NodeId);
             fn check_fn_post(
                 a: syntax::visit::FnKind<'_>,
-                b: &ast::FnDecl,
                 c: Span,
                 d: ast::NodeId
             );
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 272c4f29203..5490e5e2b4d 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -587,6 +587,14 @@ impl EarlyLintPass for UnusedParens {
             }
         }
     }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        use ast::ItemKind::*;
+
+        if let Const(.., ref expr) | Static(.., ref expr) = item.kind {
+            self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None);
+        }
+    }
 }
 
 declare_lint! {
diff --git a/src/librustc_macros/src/lift.rs b/src/librustc_macros/src/lift.rs
index 1b91fc5018a..a246b34b2c2 100644
--- a/src/librustc_macros/src/lift.rs
+++ b/src/librustc_macros/src/lift.rs
@@ -1,7 +1,5 @@
-use proc_macro2;
 use quote::quote;
 use syn::{self, parse_quote};
-use synstructure;
 
 pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     s.add_bounds(synstructure::AddBounds::Generics);
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index f680b0d64cd..6dc4f7f2515 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -2,7 +2,6 @@ use itertools::Itertools;
 use proc_macro::TokenStream;
 use proc_macro2::{Delimiter, TokenTree};
 use quote::quote;
-use syn;
 use syn::parse::{Parse, ParseStream, Result};
 use syn::punctuated::Punctuated;
 use syn::spanned::Spanned;
diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs
index c692c7f3995..feddcd5f994 100644
--- a/src/librustc_macros/src/symbols.rs
+++ b/src/librustc_macros/src/symbols.rs
@@ -1,7 +1,6 @@
 use proc_macro::TokenStream;
 use quote::quote;
 use std::collections::HashSet;
-use syn;
 use syn::parse::{Parse, ParseStream, Result};
 use syn::{braced, parse_macro_input, Ident, LitStr, Token};
 
diff --git a/src/librustc_macros/src/type_foldable.rs b/src/librustc_macros/src/type_foldable.rs
index 3d58984a900..687401e3344 100644
--- a/src/librustc_macros/src/type_foldable.rs
+++ b/src/librustc_macros/src/type_foldable.rs
@@ -1,6 +1,4 @@
 use quote::quote;
-use syn;
-use synstructure;
 
 pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index b0b9790abb1..b49e7b7f0d9 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -397,14 +397,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
             (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
                 first_borrow_desc = "first ";
-                self.cannot_mutably_borrow_multiply(
+                let mut err = self.cannot_mutably_borrow_multiply(
                     span,
                     &desc_place,
                     &msg_place,
                     issued_span,
                     &msg_borrow,
                     None,
-                )
+                );
+                self.suggest_split_at_mut_if_applicable(
+                    &mut err,
+                    &place,
+                    &issued_borrow.borrowed_place,
+                );
+                err
             }
 
             (BorrowKind::Unique, BorrowKind::Unique) => {
@@ -549,6 +555,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
+    fn suggest_split_at_mut_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        place: &Place<'tcx>,
+        borrowed_place: &Place<'tcx>,
+    ) {
+        match (&place.projection[..], &borrowed_place.projection[..]) {
+            ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) => {
+                err.help(
+                    "consider using `.split_at_mut(position)` or similar method to obtain \
+                     two mutable non-overlapping sub-slices",
+                );
+            }
+            _ => {}
+        }
+    }
+
     /// Returns the description of the root place for a conflicting borrow and the full
     /// descriptions of the places that caused the conflict.
     ///
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index cd6d94357e4..f85da760ada 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -218,19 +218,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 };
                 self.write_scalar(val, dest)?;
             }
-            sym::unchecked_shl | sym::unchecked_shr => {
+            sym::unchecked_shl
+            | sym::unchecked_shr
+            | sym::unchecked_add
+            | sym::unchecked_sub
+            | sym::unchecked_mul
+            | sym::unchecked_div
+            | sym::unchecked_rem => {
                 let l = self.read_immediate(args[0])?;
                 let r = self.read_immediate(args[1])?;
                 let bin_op = match intrinsic_name {
                     sym::unchecked_shl => BinOp::Shl,
                     sym::unchecked_shr => BinOp::Shr,
+                    sym::unchecked_add => BinOp::Add,
+                    sym::unchecked_sub => BinOp::Sub,
+                    sym::unchecked_mul => BinOp::Mul,
+                    sym::unchecked_div => BinOp::Div,
+                    sym::unchecked_rem => BinOp::Rem,
                     _ => bug!("Already checked for int ops"),
                 };
                 let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?;
                 if overflowed {
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val = self.force_bits(r.to_scalar()?, layout.size)?;
-                    throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name);
+                    if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
+                        throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name);
+                    } else {
+                        throw_ub_format!("Overflow executing `{}`", intrinsic_name);
+                    }
                 }
                 self.write_scalar(val, dest)?;
             }
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index b1cab591fd9..7c015c7a1d7 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -1,3 +1,4 @@
+use super::ty::AllowPlus;
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
 use rustc_ast_pretty::pprust;
@@ -693,11 +694,11 @@ impl<'a> Parser<'a> {
 
     pub(super) fn maybe_report_ambiguous_plus(
         &mut self,
-        allow_plus: bool,
+        allow_plus: AllowPlus,
         impl_dyn_multi: bool,
         ty: &Ty,
     ) {
-        if !allow_plus && impl_dyn_multi {
+        if matches!(allow_plus, AllowPlus::No) && impl_dyn_multi {
             let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
             self.struct_span_err(ty.span, "ambiguous `+` in a type")
                 .span_suggestion(
@@ -712,11 +713,11 @@ impl<'a> Parser<'a> {
 
     pub(super) fn maybe_recover_from_bad_type_plus(
         &mut self,
-        allow_plus: bool,
+        allow_plus: AllowPlus,
         ty: &Ty,
     ) -> PResult<'a, ()> {
         // Do not add `+` to expected tokens.
-        if !allow_plus || !self.token.is_like_plus() {
+        if matches!(allow_plus, AllowPlus::No) || !self.token.is_like_plus() {
             return Ok(());
         }
 
@@ -937,47 +938,6 @@ impl<'a> Parser<'a> {
         self.expect(&token::Semi).map(drop) // Error unconditionally
     }
 
-    pub(super) fn parse_semi_or_incorrect_foreign_fn_body(
-        &mut self,
-        ident: &Ident,
-        extern_sp: Span,
-    ) -> PResult<'a, ()> {
-        if self.token != token::Semi {
-            // This might be an incorrect fn definition (#62109).
-            let parser_snapshot = self.clone();
-            match self.parse_inner_attrs_and_block() {
-                Ok((_, body)) => {
-                    self.struct_span_err(ident.span, "incorrect `fn` inside `extern` block")
-                        .span_label(ident.span, "can't have a body")
-                        .span_label(body.span, "this body is invalid here")
-                        .span_label(
-                            extern_sp,
-                            "`extern` blocks define existing foreign functions and `fn`s \
-                             inside of them cannot have a body",
-                        )
-                        .help(
-                            "you might have meant to write a function accessible through ffi, \
-                               which can be done by writing `extern fn` outside of the \
-                               `extern` block",
-                        )
-                        .note(
-                            "for more information, visit \
-                               https://doc.rust-lang.org/std/keyword.extern.html",
-                        )
-                        .emit();
-                }
-                Err(mut err) => {
-                    err.cancel();
-                    mem::replace(self, parser_snapshot);
-                    self.expect_semi()?;
-                }
-            }
-        } else {
-            self.bump();
-        }
-        Ok(())
-    }
-
     /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
     /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
     pub(super) fn recover_incorrect_await_syntax(
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 0d12f8cf6c0..d9832141695 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -1,4 +1,5 @@
 use super::pat::{GateOr, PARAM_EXPECTED};
+use super::ty::{AllowPlus, RecoverQPath};
 use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
@@ -1399,7 +1400,7 @@ impl<'a> Parser<'a> {
             self.expect_or()?;
             args
         };
-        let output = self.parse_ret_ty(true, true)?;
+        let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes)?;
 
         Ok(P(FnDecl { inputs, output }))
     }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index b7f299e56ae..07d8bae4725 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -1,4 +1,5 @@
 use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
+use super::ty::{AllowPlus, RecoverQPath};
 use super::{FollowedByType, Parser, PathStyle};
 
 use crate::maybe_whole;
@@ -96,7 +97,6 @@ impl<'a> Parser<'a> {
         }
 
         if self.eat_keyword(kw::Extern) {
-            let extern_sp = self.prev_span;
             if self.eat_keyword(kw::Crate) {
                 return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
             }
@@ -114,7 +114,7 @@ impl<'a> Parser<'a> {
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             } else if self.check(&token::OpenDelim(token::Brace)) {
-                return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs, extern_sp)?));
+                return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?));
             }
 
             self.unexpected()?;
@@ -1045,7 +1045,6 @@ impl<'a> Parser<'a> {
         abi: Option<StrLit>,
         visibility: Visibility,
         mut attrs: Vec<Attribute>,
-        extern_sp: Span,
     ) -> PResult<'a, P<Item>> {
         self.expect(&token::OpenDelim(token::Brace))?;
 
@@ -1053,7 +1052,7 @@ impl<'a> Parser<'a> {
 
         let mut foreign_items = vec![];
         while !self.eat(&token::CloseDelim(token::Brace)) {
-            foreign_items.push(self.parse_foreign_item(extern_sp)?);
+            foreign_items.push(self.parse_foreign_item()?);
         }
 
         let prev_span = self.prev_span;
@@ -1063,51 +1062,42 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a foreign item.
-    pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, P<ForeignItem>> {
+    pub fn parse_foreign_item(&mut self) -> PResult<'a, P<ForeignItem>> {
         maybe_whole!(self, NtForeignItem, |ni| ni);
 
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
         let visibility = self.parse_visibility(FollowedByType::No)?;
 
+        // FOREIGN TYPE ITEM
+        if self.check_keyword(kw::Type) {
+            return self.parse_item_foreign_type(visibility, lo, attrs);
+        }
+
         // FOREIGN STATIC ITEM
-        // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
-        if self.check_keyword(kw::Static) || self.token.is_keyword(kw::Const) {
-            if self.token.is_keyword(kw::Const) {
-                let mut err =
-                    self.struct_span_err(self.token.span, "extern items cannot be `const`");
+        if self.is_static_global() {
+            self.bump(); // `static`
+            return self.parse_item_foreign_static(visibility, lo, attrs);
+        }
 
-                // The user wrote 'const fn'
-                if self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) {
-                    err.emit();
-                    // Consume `const`
-                    self.bump();
-                    // Consume `unsafe` if present, since `extern` blocks
-                    // don't allow it. This will leave behind a plain 'fn'
-                    self.eat_keyword(kw::Unsafe);
-                    // Treat 'const fn` as a plain `fn` for error recovery purposes.
-                    // We've already emitted an error, so compilation is guaranteed
-                    // to fail
-                    return Ok(self.parse_item_foreign_fn(visibility, lo, attrs, extern_sp)?);
-                }
-                err.span_suggestion(
-                    self.token.span,
+        // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
+        if self.is_kw_followed_by_ident(kw::Const) {
+            self.bump(); // `const`
+            self.struct_span_err(self.prev_span, "extern items cannot be `const`")
+                .span_suggestion(
+                    self.prev_span,
                     "try using a static value",
                     "static".to_owned(),
                     Applicability::MachineApplicable,
-                );
-                err.emit();
-            }
-            self.bump(); // `static` or `const`
-            return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
+                )
+                .emit();
+            return self.parse_item_foreign_static(visibility, lo, attrs);
         }
+
         // FOREIGN FUNCTION ITEM
-        if self.check_keyword(kw::Fn) {
-            return Ok(self.parse_item_foreign_fn(visibility, lo, attrs, extern_sp)?);
-        }
-        // FOREIGN TYPE ITEM
-        if self.check_keyword(kw::Type) {
-            return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
+        const MAY_INTRODUCE_FN: &[Symbol] = &[kw::Const, kw::Async, kw::Unsafe, kw::Extern, kw::Fn];
+        if MAY_INTRODUCE_FN.iter().any(|&kw| self.check_keyword(kw)) {
+            return self.parse_item_foreign_fn(visibility, lo, attrs);
         }
 
         match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
@@ -1726,14 +1716,14 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         vis: Visibility,
-        attrs: Vec<Attribute>,
+        mut attrs: Vec<Attribute>,
         header: FnHeader,
     ) -> PResult<'a, Option<P<Item>>> {
         let cfg = ParamCfg { is_name_required: |_| true };
         let (ident, decl, generics) = self.parse_fn_sig(&cfg)?;
-        let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
+        let body = self.parse_fn_body(&mut false, &mut attrs)?;
         let kind = ItemKind::Fn(FnSig { decl, header }, generics, body);
-        self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
+        self.mk_item_with_info(attrs, lo, vis, (ident, kind, None))
     }
 
     /// Parses a function declaration from a foreign module.
@@ -1741,15 +1731,14 @@ impl<'a> Parser<'a> {
         &mut self,
         vis: ast::Visibility,
         lo: Span,
-        attrs: Vec<Attribute>,
-        extern_sp: Span,
+        mut attrs: Vec<Attribute>,
     ) -> PResult<'a, P<ForeignItem>> {
         let cfg = ParamCfg { is_name_required: |_| true };
-        self.expect_keyword(kw::Fn)?;
+        let header = self.parse_fn_front_matter()?;
         let (ident, decl, generics) = self.parse_fn_sig(&cfg)?;
-        let span = lo.to(self.token.span);
-        self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
-        let kind = ForeignItemKind::Fn(decl, generics);
+        let body = self.parse_fn_body(&mut false, &mut attrs)?;
+        let kind = ForeignItemKind::Fn(FnSig { header, decl }, generics, body);
+        let span = lo.to(self.prev_span);
         Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None }))
     }
 
@@ -1760,45 +1749,40 @@ impl<'a> Parser<'a> {
         is_name_required: fn(&token::Token) -> bool,
     ) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
         let header = self.parse_fn_front_matter()?;
-        let (ident, decl, generics) = self.parse_fn_sig(&ParamCfg { is_name_required })?;
-        let sig = FnSig { header, decl };
-        let body = self.parse_assoc_fn_body(at_end, attrs)?;
-        Ok((ident, AssocItemKind::Fn(sig, body), generics))
+        let (ident, decl, generics) = self.parse_fn_sig(&&ParamCfg { is_name_required })?;
+        let body = self.parse_fn_body(at_end, attrs)?;
+        Ok((ident, AssocItemKind::Fn(FnSig { header, decl }, body), generics))
     }
 
-    /// Parse the "body" of a method in an associated item definition.
+    /// Parse the "body" of a function.
     /// This can either be `;` when there's no body,
-    /// or e.g. a block when the method is a provided one.
-    fn parse_assoc_fn_body(
+    /// or e.g. a block when the function is a provided one.
+    fn parse_fn_body(
         &mut self,
         at_end: &mut bool,
         attrs: &mut Vec<Attribute>,
     ) -> PResult<'a, Option<P<Block>>> {
-        Ok(match self.token.kind {
+        let (inner_attrs, body) = match self.token.kind {
             token::Semi => {
-                debug!("parse_assoc_fn_body(): parsing required method");
                 self.bump();
-                *at_end = true;
-                None
+                (Vec::new(), None)
             }
             token::OpenDelim(token::Brace) => {
-                debug!("parse_assoc_fn_body(): parsing provided method");
-                *at_end = true;
-                let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-                attrs.extend(inner_attrs.iter().cloned());
-                Some(body)
+                let (attrs, body) = self.parse_inner_attrs_and_block()?;
+                (attrs, Some(body))
             }
             token::Interpolated(ref nt) => match **nt {
                 token::NtBlock(..) => {
-                    *at_end = true;
-                    let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-                    attrs.extend(inner_attrs.iter().cloned());
-                    Some(body)
+                    let (attrs, body) = self.parse_inner_attrs_and_block()?;
+                    (attrs, Some(body))
                 }
                 _ => return self.expected_semi_or_open_brace(),
             },
             _ => return self.expected_semi_or_open_brace(),
-        })
+        };
+        attrs.extend(inner_attrs);
+        *at_end = true;
+        Ok(body)
     }
 
     /// Parses all the "front matter" for a `fn` declaration, up to
@@ -1839,7 +1823,7 @@ impl<'a> Parser<'a> {
     fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
-        let decl = self.parse_fn_decl(cfg, true)?;
+        let decl = self.parse_fn_decl(cfg, AllowPlus::Yes)?;
         generics.where_clause = self.parse_where_clause()?;
         Ok((ident, decl, generics))
     }
@@ -1848,11 +1832,11 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_fn_decl(
         &mut self,
         cfg: &ParamCfg,
-        ret_allow_plus: bool,
+        ret_allow_plus: AllowPlus,
     ) -> PResult<'a, P<FnDecl>> {
         Ok(P(FnDecl {
             inputs: self.parse_fn_params(cfg)?,
-            output: self.parse_ret_ty(ret_allow_plus, true)?,
+            output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?,
         }))
     }
 
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index a09eb42dcfe..cb14ffb4bd0 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -1,3 +1,4 @@
+use super::ty::{AllowPlus, RecoverQPath};
 use super::{Parser, TokenType};
 use crate::maybe_whole;
 use rustc_errors::{pluralize, Applicability, PResult};
@@ -224,7 +225,7 @@ impl<'a> Parser<'a> {
                     // `(T, U) -> R`
                     let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
                     let span = ident.span.to(self.prev_span);
-                    let output = self.parse_ret_ty(false, false)?;
+                    let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No)?;
                     ParenthesizedArgs { inputs, output, span }.into()
                 };
 
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index ae8f1e4db1b..f3a69729399 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -199,7 +199,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
+    pub(super) fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
         self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index c9c2cbb98ca..990661bf6b5 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -36,6 +36,25 @@ impl BoundModifiers {
     }
 }
 
+#[derive(Copy, Clone, PartialEq)]
+pub(super) enum AllowPlus {
+    Yes,
+    No,
+}
+
+#[derive(PartialEq)]
+pub(super) enum RecoverQPath {
+    Yes,
+    No,
+}
+
+// Is `...` (`CVarArgs`) legal at this level of type parsing?
+#[derive(PartialEq)]
+enum AllowCVariadic {
+    Yes,
+    No,
+}
+
 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
 /// `IDENT<<u8 as Trait>::AssocTy>`.
 ///
@@ -48,14 +67,14 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
 impl<'a> Parser<'a> {
     /// Parses a type.
     pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true, true, false)
+        self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::No)
     }
 
     /// Parse a type suitable for a function or function pointer parameter.
     /// The difference from `parse_ty` is that this version allows `...`
     /// (`CVarArgs`) at the top level of the the type.
     pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true, true, true)
+        self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::Yes)
     }
 
     /// Parses a type in restricted contexts where `+` is not permitted.
@@ -65,18 +84,19 @@ impl<'a> Parser<'a> {
     /// Example 2: `value1 as TYPE + value2`
     ///     `+` is prohibited to avoid interactions with expression grammar.
     pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(false, true, false)
+        self.parse_ty_common(AllowPlus::No, RecoverQPath::Yes, AllowCVariadic::No)
     }
 
     /// Parses an optional return type `[ -> TY ]` in a function declaration.
     pub(super) fn parse_ret_ty(
         &mut self,
-        allow_plus: bool,
-        allow_qpath_recovery: bool,
+        allow_plus: AllowPlus,
+        recover_qpath: RecoverQPath,
     ) -> PResult<'a, FunctionRetTy> {
         Ok(if self.eat(&token::RArrow) {
             // FIXME(Centril): Can we unconditionally `allow_plus`?
-            FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?)
+            let ty = self.parse_ty_common(allow_plus, recover_qpath, AllowCVariadic::No)?;
+            FunctionRetTy::Ty(ty)
         } else {
             FunctionRetTy::Default(self.token.span.shrink_to_lo())
         })
@@ -84,11 +104,11 @@ impl<'a> Parser<'a> {
 
     fn parse_ty_common(
         &mut self,
-        allow_plus: bool,
-        allow_qpath_recovery: bool,
-        // Is `...` (`CVarArgs`) legal in the immediate top level call?
-        allow_c_variadic: bool,
+        allow_plus: AllowPlus,
+        recover_qpath: RecoverQPath,
+        allow_c_variadic: AllowCVariadic,
     ) -> PResult<'a, P<Ty>> {
+        let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
         maybe_whole!(self, NtTy, |x| x);
 
@@ -124,7 +144,7 @@ impl<'a> Parser<'a> {
                 self.parse_ty_bare_fn(lifetime_defs)?
             } else {
                 let path = self.parse_path(PathStyle::Type)?;
-                let parse_plus = allow_plus && self.check_plus();
+                let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
                 self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
             }
         } else if self.eat_keyword(kw::Impl) {
@@ -144,7 +164,7 @@ impl<'a> Parser<'a> {
         } else if self.token.is_path_start() {
             self.parse_path_start_ty(lo, allow_plus)?
         } else if self.eat(&token::DotDotDot) {
-            if allow_c_variadic {
+            if allow_c_variadic == AllowCVariadic::Yes {
                 TyKind::CVarArgs
             } else {
                 // FIXME(Centril): Should we just allow `...` syntactically
@@ -172,7 +192,7 @@ impl<'a> Parser<'a> {
     /// Parses either:
     /// - `(TYPE)`, a parenthesized type.
     /// - `(TYPE,)`, a tuple with a single field of type TYPE.
-    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> {
+    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
         let mut trailing_plus = false;
         let (ts, trailing) = self.parse_paren_comma_seq(|p| {
             let ty = p.parse_ty()?;
@@ -182,7 +202,7 @@ impl<'a> Parser<'a> {
 
         if ts.len() == 1 && !trailing {
             let ty = ts.into_iter().nth(0).unwrap().into_inner();
-            let maybe_bounds = allow_plus && self.token.is_like_plus();
+            let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
             match ty.kind {
                 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
                 TyKind::Path(None, path) if maybe_bounds => {
@@ -288,7 +308,8 @@ impl<'a> Parser<'a> {
         let unsafety = self.parse_unsafety();
         let ext = self.parse_extern()?;
         self.expect_keyword(kw::Fn)?;
-        let decl = self.parse_fn_decl(&ParamCfg { is_name_required: |_| false }, false)?;
+        let cfg = ParamCfg { is_name_required: |_| false };
+        let decl = self.parse_fn_decl(&cfg, AllowPlus::No)?;
         Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl })))
     }
 
@@ -326,7 +347,7 @@ impl<'a> Parser<'a> {
     /// 1. a type macro, `mac!(...)`,
     /// 2. a bare trait object, `B0 + ... + Bn`,
     /// 3. or a path, `path::to::MyType`.
-    fn parse_path_start_ty(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> {
+    fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
         // Simple path
         let path = self.parse_path(PathStyle::Type)?;
         if self.eat(&token::Not) {
@@ -336,7 +357,7 @@ impl<'a> Parser<'a> {
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
             }))
-        } else if allow_plus && self.check_plus() {
+        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
             self.parse_remaining_bounds(Vec::new(), path, lo, true)
         } else {
@@ -359,7 +380,7 @@ impl<'a> Parser<'a> {
         &mut self,
         colon_span: Option<Span>,
     ) -> PResult<'a, GenericBounds> {
-        self.parse_generic_bounds_common(true, colon_span)
+        self.parse_generic_bounds_common(AllowPlus::Yes, colon_span)
     }
 
     /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
@@ -367,7 +388,7 @@ impl<'a> Parser<'a> {
     /// See `parse_generic_bound` for the `BOUND` grammar.
     fn parse_generic_bounds_common(
         &mut self,
-        allow_plus: bool,
+        allow_plus: AllowPlus,
         colon_span: Option<Span>,
     ) -> PResult<'a, GenericBounds> {
         let mut bounds = Vec::new();
@@ -377,7 +398,7 @@ impl<'a> Parser<'a> {
                 Ok(bound) => bounds.push(bound),
                 Err(neg_sp) => negative_bounds.push(neg_sp),
             }
-            if !allow_plus || !self.eat_plus() {
+            if allow_plus == AllowPlus::No || !self.eat_plus() {
                 break;
             }
         }
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 2ff9d744f2c..9367909d10c 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -15,7 +15,6 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{Node, PatKind, TyKind};
 use rustc_session::lint;
 
-use rustc_span;
 use rustc_span::symbol::sym;
 use syntax::{ast, attr};
 
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index b6ca2b3a595..c6c201fa38e 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -302,19 +302,18 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         ast_visit::walk_ty(self, t)
     }
 
-    fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, fd: &'v ast::FnDecl, s: Span, _: NodeId) {
-        self.record("FnDecl", Id::None, fd);
-        ast_visit::walk_fn(self, fk, fd, s)
-    }
-
-    fn visit_trait_item(&mut self, ti: &'v ast::AssocItem) {
-        self.record("TraitItem", Id::None, ti);
-        ast_visit::walk_trait_item(self, ti)
-    }
-
-    fn visit_impl_item(&mut self, ii: &'v ast::AssocItem) {
-        self.record("ImplItem", Id::None, ii);
-        ast_visit::walk_impl_item(self, ii)
+    fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, s: Span, _: NodeId) {
+        self.record("FnDecl", Id::None, fk.decl());
+        ast_visit::walk_fn(self, fk, s)
+    }
+
+    fn visit_assoc_item(&mut self, item: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
+        let label = match ctxt {
+            ast_visit::AssocCtxt::Trait => "TraitItem",
+            ast_visit::AssocCtxt::Impl => "ImplItem",
+        };
+        self.record(label, Id::None, item);
+        ast_visit::walk_assoc_item(self, item, ctxt);
     }
 
     fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) {
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 7718139f6e9..b355a47c394 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -822,8 +822,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             return false;
         }
 
-        let mut changed = false;
+        let mut any_changed = false;
         self.indices2(ln, succ_ln, |this, idx, succ_idx| {
+            // This is a special case, pulled out from the code below, where we
+            // don't have to do anything. It occurs about 60-70% of the time.
+            if this.rwu_table.packed_rwus[succ_idx] == INV_INV_FALSE {
+                return;
+            }
+
+            let mut changed = false;
             let mut rwu = this.rwu_table.get(idx);
             let succ_rwu = this.rwu_table.get(succ_idx);
             if succ_rwu.reader.is_valid() && !rwu.reader.is_valid() {
@@ -843,6 +850,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
             if changed {
                 this.rwu_table.assign_unpacked(idx, rwu);
+                any_changed = true;
             }
         });
 
@@ -851,9 +859,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             ln,
             self.ln_str(succ_ln),
             first_merge,
-            changed
+            any_changed
         );
-        return changed;
+        return any_changed;
     }
 
     // Indicates that a local variable was *defined*; we know that no
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index c77b588d7fb..d6ea737385c 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -36,7 +36,7 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod
 use syntax::ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use syntax::ast::{Ident, Name};
 use syntax::token::{self, Token};
-use syntax::visit::{self, Visitor};
+use syntax::visit::{self, AssocCtxt, Visitor};
 
 use log::debug;
 use std::cell::Cell;
@@ -1234,7 +1234,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         self.parent_scope.legacy = orig_current_legacy_scope;
     }
 
-    fn visit_trait_item(&mut self, item: &'b AssocItem) {
+    fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         let parent = self.parent_scope.module;
 
         if let AssocItemKind::Macro(_) = item.kind {
@@ -1242,6 +1242,12 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
             return;
         }
 
+        if let AssocCtxt::Impl = ctxt {
+            self.resolve_visibility(&item.vis);
+            visit::walk_assoc_item(self, item, ctxt);
+            return;
+        }
+
         // Add the item to the trait info.
         let item_def_id = self.r.definitions.local_def_id(item.id);
         let (res, ns) = match item.kind {
@@ -1260,16 +1266,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         let expansion = self.parent_scope.expansion;
         self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
 
-        visit::walk_trait_item(self, item);
-    }
-
-    fn visit_impl_item(&mut self, item: &'b ast::AssocItem) {
-        if let ast::AssocItemKind::Macro(..) = item.kind {
-            self.visit_invoc(item.id);
-        } else {
-            self.resolve_visibility(&item.vis);
-            visit::walk_impl_item(self, item);
-        }
+        visit::walk_assoc_item(self, item, ctxt);
     }
 
     fn visit_token(&mut self, t: Token) {
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 696ba0e994c..3a26197c160 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -125,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     &sig.header,
                     generics,
                     &sig.decl,
-                    Some(body),
+                    body.as_deref(),
                 );
             }
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => {
@@ -213,39 +213,26 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         visit::walk_generic_param(self, param);
     }
 
-    fn visit_trait_item(&mut self, ti: &'a AssocItem) {
-        let def_data = match ti.kind {
-            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name),
-            AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ti.ident.name),
-            AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
-        };
-
-        let def = self.create_def(ti.id, def_data, ti.span);
-        self.with_parent(def, |this| visit::walk_trait_item(this, ti));
-    }
-
-    fn visit_impl_item(&mut self, ii: &'a AssocItem) {
-        let def_data = match ii.kind {
-            AssocItemKind::Fn(FnSig { ref header, ref decl }, ref body)
-                if header.asyncness.node.is_async() =>
-            {
+    fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
+        let def_data = match &i.kind {
+            AssocItemKind::Fn(FnSig { header, decl }, body) if header.asyncness.node.is_async() => {
                 return self.visit_async_fn(
-                    ii.id,
-                    ii.ident.name,
-                    ii.span,
+                    i.id,
+                    i.ident.name,
+                    i.span,
                     header,
-                    &ii.generics,
+                    &i.generics,
                     decl,
                     body.as_deref(),
                 );
             }
-            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
-            AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
-            AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
+            AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
+            AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
+            AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id),
         };
 
-        let def = self.create_def(ii.id, def_data, ii.span);
-        self.with_parent(def, |this| visit::walk_impl_item(this, ii));
+        let def = self.create_def(i.id, def_data, i.span);
+        self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
     }
 
     fn visit_pat(&mut self, pat: &'a Pat) {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index a612ad9e783..075dca8f01d 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -20,6 +20,7 @@ use syntax::ast::{self, Ident, Path};
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
+use crate::lifetimes::{ElisionFailureInfo, LifetimeContext};
 use crate::path_names_to_string;
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
@@ -48,6 +49,40 @@ crate struct ImportSuggestion {
     pub path: Path,
 }
 
+crate enum MissingLifetimeSpot<'tcx> {
+    Generics(&'tcx hir::Generics<'tcx>),
+    HigherRanked { span: Span, span_type: ForLifetimeSpanType },
+}
+
+crate enum ForLifetimeSpanType {
+    BoundEmpty,
+    BoundTail,
+    TypeEmpty,
+    TypeTail,
+}
+
+impl ForLifetimeSpanType {
+    crate fn descr(&self) -> &'static str {
+        match self {
+            Self::BoundEmpty | Self::BoundTail => "bound",
+            Self::TypeEmpty | Self::TypeTail => "type",
+        }
+    }
+
+    crate fn suggestion(&self, sugg: &str) -> String {
+        match self {
+            Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
+            Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
+        }
+    }
+}
+
+impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
+    fn into(self) -> MissingLifetimeSpot<'tcx> {
+        MissingLifetimeSpot::Generics(self)
+    }
+}
+
 /// Adjust the impl span so that just the `impl` keyword is taken by removing
 /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
 /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
@@ -1457,72 +1492,206 @@ crate fn show_candidates(
     }
 }
 
-crate fn report_missing_lifetime_specifiers(
-    sess: &Session,
-    span: Span,
-    count: usize,
-) -> DiagnosticBuilder<'_> {
-    struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
-}
+impl<'tcx> LifetimeContext<'_, 'tcx> {
+    crate fn report_missing_lifetime_specifiers(
+        &self,
+        span: Span,
+        count: usize,
+    ) -> DiagnosticBuilder<'tcx> {
+        struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0106,
+            "missing lifetime specifier{}",
+            pluralize!(count)
+        )
+    }
 
-crate fn add_missing_lifetime_specifiers_label(
-    err: &mut DiagnosticBuilder<'_>,
-    span: Span,
-    count: usize,
-    lifetime_names: &FxHashSet<ast::Ident>,
-    snippet: Option<&str>,
-    missing_named_lifetime_spots: &[&hir::Generics<'_>],
-) {
-    if count > 1 {
-        err.span_label(span, format!("expected {} lifetime parameters", count));
-    } else {
-        let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
-            err.span_suggestion(
-                span,
-                "consider using the named lifetime",
-                sugg,
-                Applicability::MaybeIncorrect,
-            );
-        };
-        let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg| {
-            err.span_label(span, "expected named lifetime parameter");
-
-            if let Some(generics) = missing_named_lifetime_spots.iter().last() {
-                let mut introduce_suggestion = vec![];
-                introduce_suggestion.push(match &generics.params {
-                    [] => (generics.span, "<'lifetime>".to_string()),
-                    [param, ..] => (param.span.shrink_to_lo(), "'lifetime, ".to_string()),
-                });
-                introduce_suggestion.push((span, sugg));
-                err.multipart_suggestion(
-                    "consider introducing a named lifetime parameter",
-                    introduce_suggestion,
-                    Applicability::MaybeIncorrect,
-                );
+    crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            lifetime_ref.span,
+            E0261,
+            "use of undeclared lifetime name `{}`",
+            lifetime_ref
+        );
+        err.span_label(lifetime_ref.span, "undeclared lifetime");
+        for missing in &self.missing_named_lifetime_spots {
+            match missing {
+                MissingLifetimeSpot::Generics(generics) => {
+                    let (span, sugg) = if let Some(param) = generics
+                        .params
+                        .iter()
+                        .filter(|p| match p.kind {
+                            hir::GenericParamKind::Type {
+                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                                ..
+                            } => false,
+                            _ => true,
+                        })
+                        .next()
+                    {
+                        (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
+                    } else {
+                        (generics.span, format!("<{}>", lifetime_ref))
+                    };
+                    err.span_suggestion(
+                        span,
+                        &format!("consider introducing lifetime `{}` here", lifetime_ref),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                MissingLifetimeSpot::HigherRanked { span, span_type } => {
+                    err.span_suggestion(
+                        *span,
+                        &format!(
+                            "consider making the {} lifetime-generic with a new `{}` lifetime",
+                            span_type.descr(),
+                            lifetime_ref
+                        ),
+                        span_type.suggestion(&lifetime_ref.to_string()),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.note(
+                        "for more information on higher-ranked polymorphism, visit \
+                            https://doc.rust-lang.org/nomicon/hrtb.html",
+                    );
+                }
             }
-        };
+        }
+        err.emit();
+    }
 
-        match (lifetime_names.len(), lifetime_names.iter().next(), snippet) {
-            (1, Some(name), Some("&")) => {
-                suggest_existing(err, format!("&{} ", name));
-            }
-            (1, Some(name), Some("'_")) => {
-                suggest_existing(err, name.to_string());
-            }
-            (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
-                suggest_existing(err, format!("{}<{}>", snippet, name));
-            }
-            (0, _, Some("&")) => {
-                suggest_new(err, "&'lifetime ".to_string());
-            }
-            (0, _, Some("'_")) => {
-                suggest_new(err, "'lifetime".to_string());
-            }
-            (0, _, Some(snippet)) if !snippet.ends_with(">") => {
-                suggest_new(err, format!("{}<'lifetime>", snippet));
+    crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
+        if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res {
+            if [
+                self.tcx.lang_items().fn_once_trait(),
+                self.tcx.lang_items().fn_trait(),
+                self.tcx.lang_items().fn_mut_trait(),
+            ]
+            .contains(&Some(did))
+            {
+                let (span, span_type) = match &trait_ref.bound_generic_params {
+                    [] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
+                    [.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
+                };
+                self.missing_named_lifetime_spots
+                    .push(MissingLifetimeSpot::HigherRanked { span, span_type });
+                return true;
             }
-            _ => {
-                err.span_label(span, "expected lifetime parameter");
+        };
+        false
+    }
+
+    crate fn add_missing_lifetime_specifiers_label(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        span: Span,
+        count: usize,
+        lifetime_names: &FxHashSet<ast::Ident>,
+        params: &[ElisionFailureInfo],
+    ) {
+        if count > 1 {
+            err.span_label(span, format!("expected {} lifetime parameters", count));
+        } else {
+            let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
+            let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
+                err.span_suggestion(
+                    span,
+                    "consider using the named lifetime",
+                    sugg,
+                    Applicability::MaybeIncorrect,
+                );
+            };
+            let suggest_new =
+                |err: &mut DiagnosticBuilder<'_>, sugg: &str| {
+                    err.span_label(span, "expected named lifetime parameter");
+
+                    for missing in self.missing_named_lifetime_spots.iter().rev() {
+                        let mut introduce_suggestion = vec![];
+                        let msg;
+                        let should_break;
+                        introduce_suggestion.push(match missing {
+                        MissingLifetimeSpot::Generics(generics) => {
+                            msg = "consider introducing a named lifetime parameter".to_string();
+                            should_break = true;
+                            if let Some(param) = generics.params.iter().filter(|p| match p.kind {
+                                hir::GenericParamKind::Type {
+                                    synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                                    ..
+                                } => false,
+                                _ => true,
+                            }).next() {
+                                (param.span.shrink_to_lo(), "'a, ".to_string())
+                            } else {
+                                (generics.span, "<'a>".to_string())
+                            }
+                        }
+                        MissingLifetimeSpot::HigherRanked { span, span_type } => {
+                            msg = format!(
+                                "consider making the {} lifetime-generic with a new `'a` lifetime",
+                                span_type.descr(),
+                            );
+                            should_break = false;
+                            err.note(
+                                "for more information on higher-ranked polymorphism, visit \
+                             https://doc.rust-lang.org/nomicon/hrtb.html",
+                            );
+                            (*span, span_type.suggestion("'a"))
+                        }
+                    });
+                        for param in params {
+                            if let Ok(snippet) =
+                                self.tcx.sess.source_map().span_to_snippet(param.span)
+                            {
+                                if snippet.starts_with("&") && !snippet.starts_with("&'") {
+                                    introduce_suggestion
+                                        .push((param.span, format!("&'a {}", &snippet[1..])));
+                                } else if snippet.starts_with("&'_ ") {
+                                    introduce_suggestion
+                                        .push((param.span, format!("&'a {}", &snippet[4..])));
+                                }
+                            }
+                        }
+                        introduce_suggestion.push((span, sugg.to_string()));
+                        err.multipart_suggestion(
+                            &msg,
+                            introduce_suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
+                        if should_break {
+                            break;
+                        }
+                    }
+                };
+
+            match (
+                lifetime_names.len(),
+                lifetime_names.iter().next(),
+                snippet.as_ref().map(|s| s.as_str()),
+            ) {
+                (1, Some(name), Some("&")) => {
+                    suggest_existing(err, format!("&{} ", name));
+                }
+                (1, Some(name), Some("'_")) => {
+                    suggest_existing(err, name.to_string());
+                }
+                (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
+                    suggest_existing(err, format!("{}<{}>", snippet, name));
+                }
+                (0, _, Some("&")) => {
+                    suggest_new(err, "&'a ");
+                }
+                (0, _, Some("'_")) => {
+                    suggest_new(err, "'a");
+                }
+                (0, _, Some(snippet)) if !snippet.ends_with(">") => {
+                    suggest_new(err, &format!("{}<'a>", snippet));
+                }
+                _ => {
+                    err.span_label(span, "expected lifetime parameter");
+                }
             }
         }
     }
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index f1622af130e..01a0e568137 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -24,7 +24,7 @@ use smallvec::{smallvec, SmallVec};
 use syntax::ast::*;
 use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::visit::{self, FnKind, Visitor};
+use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use syntax::{unwrap_or, walk_list};
 
 use log::debug;
@@ -437,7 +437,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     }
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
-            ForeignItemKind::Fn(_, ref generics) => {
+            ForeignItemKind::Fn(_, ref generics, _) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
@@ -452,13 +452,15 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
             }
         }
     }
-    fn visit_fn(&mut self, fn_kind: FnKind<'ast>, declaration: &'ast FnDecl, sp: Span, _: NodeId) {
-        let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
-        debug!("(resolving function) entering function");
+    fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) {
         let rib_kind = match fn_kind {
-            FnKind::ItemFn(..) => FnItemRibKind,
-            FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind,
+            FnKind::Fn(FnCtxt::Foreign, ..) => return visit::walk_fn(self, fn_kind, sp),
+            FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind,
+            FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind,
         };
+        let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
+        debug!("(resolving function) entering function");
+        let declaration = fn_kind.decl();
 
         // Create a value rib for the function.
         self.with_rib(ValueNS, rib_kind, |this| {
@@ -471,8 +473,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
 
                 // Resolve the function body, potentially inside the body of an async closure
                 match fn_kind {
-                    FnKind::ItemFn(.., body) | FnKind::Method(.., body) => this.visit_block(body),
-                    FnKind::Closure(body) => this.visit_expr(body),
+                    FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
+                    FnKind::Closure(_, body) => this.visit_expr(body),
                 };
 
                 debug!("(resolving function) leaving function");
@@ -843,12 +845,16 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                     });
                                                 }
                                             }
-                                            AssocItemKind::Fn(_, _) => {
-                                                visit::walk_trait_item(this, trait_item)
-                                            }
-                                            AssocItemKind::TyAlias(..) => {
-                                                visit::walk_trait_item(this, trait_item)
-                                            }
+                                            AssocItemKind::Fn(_, _) => visit::walk_assoc_item(
+                                                this,
+                                                trait_item,
+                                                AssocCtxt::Trait,
+                                            ),
+                                            AssocItemKind::TyAlias(..) => visit::walk_assoc_item(
+                                                this,
+                                                trait_item,
+                                                AssocCtxt::Trait,
+                                            ),
                                             AssocItemKind::Macro(_) => {
                                                 panic!("unexpanded macro in resolve!")
                                             }
@@ -1128,7 +1134,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                 );
 
                                                 this.with_constant_rib(|this| {
-                                                    visit::walk_impl_item(this, impl_item)
+                                                    visit::walk_assoc_item(
+                                                        this,
+                                                        impl_item,
+                                                        AssocCtxt::Impl,
+                                                    )
                                                 });
                                             }
                                             AssocItemKind::Fn(..) => {
@@ -1139,7 +1149,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                                       impl_item.span,
                                                     |n, s| MethodNotMemberOfTrait(n, s));
 
-                                                visit::walk_impl_item(this, impl_item);
+                                                visit::walk_assoc_item(
+                                                    this,
+                                                    impl_item,
+                                                    AssocCtxt::Impl,
+                                                )
                                             }
                                             AssocItemKind::TyAlias(_, _) => {
                                                 // If this is a trait impl, ensure the type
@@ -1149,7 +1163,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                                       impl_item.span,
                                                     |n, s| TypeNotMemberOfTrait(n, s));
 
-                                                visit::walk_impl_item(this, impl_item);
+                                                visit::walk_assoc_item(
+                                                    this,
+                                                    impl_item,
+                                                    AssocCtxt::Impl,
+                                                )
                                             }
                                             AssocItemKind::Macro(_) =>
                                                 panic!("unexpanded macro in resolve!"),
diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs
index 6e9ed5fdc17..0ba9b4f1706 100644
--- a/src/librustc_resolve/lifetimes.rs
+++ b/src/librustc_resolve/lifetimes.rs
@@ -5,9 +5,7 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use crate::diagnostics::{
-    add_missing_lifetime_specifiers_label, report_missing_lifetime_specifiers,
-};
+use crate::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
@@ -153,8 +151,8 @@ struct NamedRegionMap {
     object_lifetime_defaults: HirIdMap<Vec<ObjectLifetimeDefault>>,
 }
 
-struct LifetimeContext<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
+crate struct LifetimeContext<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
     map: &'a mut NamedRegionMap,
     scope: ScopeRef<'a>,
 
@@ -186,7 +184,7 @@ struct LifetimeContext<'a, 'tcx> {
 
     /// When encountering an undefined named lifetime, we will suggest introducing it in these
     /// places.
-    missing_named_lifetime_spots: Vec<&'tcx hir::Generics<'tcx>>,
+    crate missing_named_lifetime_spots: Vec<MissingLifetimeSpot<'tcx>>,
 }
 
 #[derive(Debug)]
@@ -264,13 +262,14 @@ enum Elide {
 }
 
 #[derive(Clone, Debug)]
-struct ElisionFailureInfo {
+crate struct ElisionFailureInfo {
     /// Where we can find the argument pattern.
     parent: Option<hir::BodyId>,
     /// The index of the argument in the original definition.
     index: usize,
     lifetime_count: usize,
     have_bound_regions: bool,
+    crate span: Span,
 }
 
 type ScopeRef<'a> = &'a Scope<'a>;
@@ -389,7 +388,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
             hir::ItemKind::Fn(ref sig, ref generics, _) => {
-                self.missing_named_lifetime_spots.push(generics);
+                self.missing_named_lifetime_spots.push(generics.into());
                 self.visit_early_late(None, &sig.decl, generics, |this| {
                     intravisit::walk_item(this, item);
                 });
@@ -424,7 +423,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             | hir::ItemKind::Trait(_, _, ref generics, ..)
             | hir::ItemKind::TraitAlias(ref generics, ..)
             | hir::ItemKind::Impl { ref generics, .. } => {
-                self.missing_named_lifetime_spots.push(generics);
+                self.missing_named_lifetime_spots.push(generics.into());
 
                 // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
                 // This is not true for other kinds of items.x
@@ -492,6 +491,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let next_early_index = self.next_early_index();
                 let was_in_fn_syntax = self.is_in_fn_syntax;
                 self.is_in_fn_syntax = true;
+                let lifetime_span: Option<Span> = c
+                    .generic_params
+                    .iter()
+                    .filter_map(|param| match param.kind {
+                        GenericParamKind::Lifetime { .. } => Some(param.span),
+                        _ => None,
+                    })
+                    .last();
+                let (span, span_type) = if let Some(span) = lifetime_span {
+                    (span.shrink_to_hi(), ForLifetimeSpanType::TypeTail)
+                } else {
+                    (ty.span.shrink_to_lo(), ForLifetimeSpanType::TypeEmpty)
+                };
+                self.missing_named_lifetime_spots
+                    .push(MissingLifetimeSpot::HigherRanked { span, span_type });
                 let scope = Scope::Binder {
                     lifetimes: c
                         .generic_params
@@ -514,6 +528,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     this.check_lifetime_params(old_scope, &c.generic_params);
                     intravisit::walk_ty(this, ty);
                 });
+                self.missing_named_lifetime_spots.pop();
                 self.is_in_fn_syntax = was_in_fn_syntax;
             }
             hir::TyKind::TraitObject(bounds, ref lifetime) => {
@@ -696,7 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
-        self.missing_named_lifetime_spots.push(&trait_item.generics);
+        self.missing_named_lifetime_spots.push((&trait_item.generics).into());
         match trait_item.kind {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
@@ -753,7 +768,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
         use self::hir::ImplItemKind::*;
-        self.missing_named_lifetime_spots.push(&impl_item.generics);
+        self.missing_named_lifetime_spots.push((&impl_item.generics).into());
         match impl_item.kind {
             Method(ref sig, _) => {
                 let tcx = self.tcx;
@@ -953,6 +968,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     ) {
         debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
 
+        let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref);
         if !self.trait_ref_hack
             || trait_ref.bound_generic_params.iter().any(|param| match param.kind {
                 GenericParamKind::Lifetime { .. } => true,
@@ -988,10 +1004,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             self.with(scope, |old_scope, this| {
                 this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
                 walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
-                this.visit_trait_ref(&trait_ref.trait_ref)
+                this.visit_trait_ref(&trait_ref.trait_ref);
             })
         } else {
-            self.visit_trait_ref(&trait_ref.trait_ref)
+            self.visit_trait_ref(&trait_ref.trait_ref);
+        }
+        if should_pop_missing_lt {
+            self.missing_named_lifetime_spots.pop();
         }
     }
 }
@@ -1824,29 +1843,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
             self.insert_lifetime(lifetime_ref, def);
         } else {
-            let mut err = struct_span_err!(
-                self.tcx.sess,
-                lifetime_ref.span,
-                E0261,
-                "use of undeclared lifetime name `{}`",
-                lifetime_ref
-            );
-            err.span_label(lifetime_ref.span, "undeclared lifetime");
-            if !self.is_in_fn_syntax {
-                for generics in &self.missing_named_lifetime_spots {
-                    let (span, sugg) = match &generics.params {
-                        [] => (generics.span, format!("<{}>", lifetime_ref)),
-                        [param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)),
-                    };
-                    err.span_suggestion(
-                        span,
-                        &format!("consider introducing lifetime `{}` here", lifetime_ref),
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            }
-            err.emit();
+            self.emit_undeclared_lifetime_error(lifetime_ref);
         }
     }
 
@@ -2230,6 +2227,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     index: i,
                     lifetime_count: gather.lifetimes.len(),
                     have_bound_regions: gather.have_bound_regions,
+                    span: input.span,
                 }
             })
             .collect();
@@ -2385,7 +2383,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
         };
 
-        let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len());
+        let mut err = self.report_missing_lifetime_specifiers(span, lifetime_refs.len());
         let mut add_label = true;
 
         if let Some(params) = error {
@@ -2394,13 +2392,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
         }
         if add_label {
-            add_missing_lifetime_specifiers_label(
+            self.add_missing_lifetime_specifiers_label(
                 &mut err,
                 span,
                 lifetime_refs.len(),
                 &lifetime_names,
-                self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
-                &self.missing_named_lifetime_spots,
+                error.map(|p| &p[..]).unwrap_or(&[]),
             );
         }
 
@@ -2442,8 +2439,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let elided_len = elided_params.len();
 
         for (i, info) in elided_params.into_iter().enumerate() {
-            let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions } = info;
+            let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } =
+                info;
 
+            db.span_label(span, "");
             let help_name = if let Some(ident) =
                 parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident())
             {
@@ -2477,7 +2476,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         if len == 0 {
             db.help(
                 "this function's return type contains a borrowed value, \
-                but there is no value for it to be borrowed from",
+                 but there is no value for it to be borrowed from",
             );
             self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
         } else if elided_len == 0 {
@@ -2491,14 +2490,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         } else if elided_len == 1 {
             db.help(&format!(
                 "this function's return type contains a borrowed value, \
-                but the signature does not say which {} it is borrowed from",
+                 but the signature does not say which {} it is borrowed from",
                 m
             ));
             true
         } else {
             db.help(&format!(
                 "this function's return type contains a borrowed value, \
-                but the signature does not say whether it is borrowed from {}",
+                 but the signature does not say whether it is borrowed from {}",
                 m
             ));
             true
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 3f436a1e27c..5ce81c104e1 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -358,7 +358,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         decl: &'l ast::FnDecl,
         header: &'l ast::FnHeader,
         ty_params: &'l ast::Generics,
-        body: &'l ast::Block,
+        body: Option<&'l ast::Block>,
     ) {
         let hir_id = self.tcx.hir().node_to_hir_id(item.id);
         self.nest_tables(item.id, |v| {
@@ -392,7 +392,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                 }
             }
 
-            v.visit_block(&body);
+            walk_list!(v, visit_block, body);
         });
     }
 
@@ -1291,7 +1291,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 }
             }
             Fn(ref sig, ref ty_params, ref body) => {
-                self.process_fn(item, &sig.decl, &sig.header, ty_params, &body)
+                self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref())
             }
             Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
             Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
@@ -1515,7 +1515,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
         let access = access_from!(self.save_ctxt, item, hir_id);
 
         match item.kind {
-            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
+                let decl = &sig.decl;
                 if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(fn_data, DefData, item.span);
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 89054441fa3..e32f4744366 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -133,7 +133,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
         );
         match item.kind {
-            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
                 filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -142,7 +142,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
-                    value: make_signature(decl, generics),
+                    value: make_signature(&sig.decl, generics),
                     parent: None,
                     children: vec![],
                     decl_id: None,
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index dbf29b6531d..6401cabdcd5 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -723,7 +723,8 @@ impl Sig for ast::ForeignItem {
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
         let id = Some(self.id);
         match self.kind {
-            ast::ForeignItemKind::Fn(ref decl, ref generics) => {
+            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
+                let decl = &sig.decl;
                 let mut text = String::new();
                 text.push_str("fn ");
 
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 813d14d616d..ad1a6c4906e 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -22,8 +22,6 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_errors::emitter::HumanReadableErrorType;
 use rustc_errors::{ColorConfig, FatalError, Handler, HandlerFlags};
 
-use getopts;
-
 use std::collections::btree_map::{
     Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
 };
@@ -816,7 +814,6 @@ mod opt {
     #![allow(dead_code)]
 
     use super::RustcOptGroup;
-    use getopts;
 
     pub type R = RustcOptGroup;
     pub type S = &'static str;
@@ -1862,7 +1859,6 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
 pub mod nightly_options {
     use super::{ErrorOutputType, OptionStability, RustcOptGroup};
     use crate::early_error;
-    use getopts;
     use rustc_feature::UnstableFeatures;
 
     pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index be0e668a467..d6b71641da5 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -11,8 +11,6 @@ use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
 
-use getopts;
-
 use std::collections::BTreeMap;
 
 use std::collections::hash_map::DefaultHasher;
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index a40d6451b95..70984917d7c 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -33,7 +33,6 @@ use rustc_data_structures::jobserver::{self, Client};
 use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
 use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
 
-use std;
 use std::cell::{self, RefCell};
 use std::env;
 use std::fmt;
@@ -133,6 +132,10 @@ pub struct Session {
     /// Mapping from ident span to path span for paths that don't exist as written, but that
     /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
     pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
+
+    /// Path for libraries that will take preference over libraries shipped by Rust.
+    /// Used by windows-gnu targets to priortize system mingw-w64 libraries.
+    pub system_library_path: OneThread<RefCell<Option<Option<PathBuf>>>>,
 }
 
 pub struct PerfStats {
@@ -1069,6 +1072,7 @@ fn build_session_(
         driver_lint_caps,
         trait_methods_not_found: Lock::new(Default::default()),
         confused_type_with_std_module: Lock::new(Default::default()),
+        system_library_path: OneThread::new(RefCell::new(Default::default())),
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index e4f8b5a0143..c060e8948e3 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -755,8 +755,13 @@ symbols! {
         u64,
         u8,
         unboxed_closures,
+        unchecked_add,
+        unchecked_div,
+        unchecked_mul,
+        unchecked_rem,
         unchecked_shl,
         unchecked_shr,
+        unchecked_sub,
         underscore_const_names,
         underscore_imports,
         underscore_lifetimes,
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 9f867cf8ab4..aa05165e3de 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -206,6 +206,14 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     }
 }
 
+fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AssocItemsIterator<'tcx> {
+    ty::AssocItemsIterator {
+        items: tcx.arena.alloc_from_iter(
+            tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
+        ),
+    }
+}
+
 fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
     tcx.hir().span_if_local(def_id).unwrap()
 }
@@ -356,6 +364,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         asyncness,
         associated_item,
         associated_item_def_ids,
+        associated_items,
         adt_sized_constraint,
         def_span,
         param_env,
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index c2123876b67..6bd120d818d 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1307,12 +1307,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             );
                         }
                     };
+                    // FIXME: point at the type params that don't have appropriate lifetimes:
+                    // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                    //                         ----  ----     ^^^^^^^
                     struct_span_err!(
                         tcx.sess,
                         binding.span,
                         E0582,
                         "binding for associated type `{}` references lifetime `{}`, \
-                                     which does not appear in the trait input types",
+                         which does not appear in the trait input types",
                         binding.item_name,
                         br_name
                     )
@@ -1438,10 +1441,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // Expand trait aliases recursively and check that only one regular (non-auto) trait
         // is used and no 'maybe' bounds are used.
-        let expanded_traits = traits::expand_trait_aliases(
-            tcx,
-            bounds.trait_bounds.iter().map(|&(a, b, _)| (a.clone(), b)),
-        );
+        let expanded_traits =
+            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
         let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
             expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
         if regular_traits.len() > 1 {
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index e4dec97183c..d436733d19a 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -250,8 +250,8 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
         )
         .span_label(span, "deref recursion limit reached")
         .help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
+            suggested_limit, tcx.crate_name,
         ))
         .emit();
     }
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 27dc03bbbe2..32bd7e4c4c1 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -3,7 +3,6 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/variance.html
 
-use arena;
 use hir::Node;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, CrateVariancesMap, TyCtxt};
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index e110545c6f2..356660763a7 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -16,7 +16,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_span;
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
 
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 22f5d0dc2c0..1b776930d7a 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -3,7 +3,6 @@ use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
-use getopts;
 use rustc::lint::Level;
 use rustc::session;
 use rustc::session::config::{
@@ -13,7 +12,6 @@ use rustc::session::config::{
 use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType};
 use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
 use rustc::session::search_paths::SearchPath;
-use rustc_driver;
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_target::spec::TargetTriple;
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a8baa89c6f1..429988db9d8 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -11,7 +11,6 @@ use rustc_hir::def::Namespace::TypeNS;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use rustc_hir::HirId;
 use rustc_interface::interface;
-use rustc_lint;
 use rustc_resolve as resolve;
 use rustc_session::lint;
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index c6706413942..6a23b230e12 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -73,8 +73,6 @@ use crate::html::markdown::{self, ErrorCodes, IdMap, Markdown, MarkdownHtml, Mar
 use crate::html::sources;
 use crate::html::{highlight, layout, static_files};
 
-use minifier;
-
 #[cfg(test)]
 mod tests;
 
@@ -3629,14 +3627,7 @@ fn render_impl(
                 for it in &i.inner_impl().items {
                     if let clean::TypedefItem(ref tydef, _) = it.inner {
                         write!(w, "<span class=\"where fmt-newline\">  ");
-                        assoc_type(
-                            w,
-                            it,
-                            &vec![],
-                            Some(&tydef.type_),
-                            AssocItemLink::Anchor(None),
-                            "",
-                        );
+                        assoc_type(w, it, &[], Some(&tydef.type_), AssocItemLink::Anchor(None), "");
                         write!(w, ";</span>");
                     }
                 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 912a40722b8..a37efc22c93 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -5,7 +5,6 @@ use std::path::PathBuf;
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::DUMMY_SP;
-use testing;
 
 use crate::config::{Options, RenderOptions};
 use crate::externalfiles::{load_string, LoadStringError};
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 50d5f70f488..332d19fbfae 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId;
 use rustc_resolve::ParentScope;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
-use syntax;
 use syntax::ast::{self, Ident};
 
 use std::ops::Range;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 936f63975a5..556dab302b8 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -20,7 +20,6 @@ use std::str;
 use syntax::ast;
 use syntax::with_globals;
 use tempfile::Builder as TempFileBuilder;
-use testing;
 
 use crate::clean::Attributes;
 use crate::config::Options;
@@ -282,7 +281,7 @@ fn run_test(
     for debugging_option_str in &options.debugging_options_strs {
         compiler.arg("-Z").arg(&debugging_option_str);
     }
-    if no_run {
+    if no_run && !compile_fail {
         compiler.arg("--emit=metadata");
     }
     compiler.arg("--target").arg(target.to_string());
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 6739d4498a6..8862226adbb 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -198,7 +198,7 @@ impl<R> BufReader<R> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "buffered_io_capacity", issue = "68558")]
+    #[unstable(feature = "buffered_io_capacity", issue = "68833")]
     pub fn capacity(&self) -> usize {
         self.buf.len()
     }
@@ -616,7 +616,7 @@ impl<W: Write> BufWriter<W> {
     /// // Calculate how many bytes can be written without flushing
     /// let without_flush = capacity - buf_writer.buffer().len();
     /// ```
-    #[unstable(feature = "buffered_io_capacity", issue = "68558")]
+    #[unstable(feature = "buffered_io_capacity", issue = "68833")]
     pub fn capacity(&self) -> usize {
         self.buf.capacity()
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 806f868ff24..f9c9f224730 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -334,12 +334,6 @@ extern crate libc;
 #[allow(unused_extern_crates)]
 extern crate unwind;
 
-// Only needed for now for the `std_detect` module until that crate changes to
-// use `cfg_if::cfg_if!`
-#[macro_use]
-#[cfg(not(test))]
-extern crate cfg_if;
-
 // During testing, this crate is not actually the "real" std library, but rather
 // it links to the real std library, which was compiled from this same source
 // code. So any lang items std defines are conditionally excluded (or else they
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 23104419978..6707f790cab 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -282,7 +282,6 @@ mod inner {
             (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
                 || (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
                 || cfg!(target_os = "fuchsia")
-                || false // last clause, used so `||` is always trailing above
         }
 
         pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
diff --git a/src/libstd/tests/run-time-detect.rs b/src/libstd/tests/run-time-detect.rs
index e39cc1eed5e..2e6d1bc8efd 100644
--- a/src/libstd/tests/run-time-detect.rs
+++ b/src/libstd/tests/run-time-detect.rs
@@ -6,6 +6,7 @@
         all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")),
         all(target_arch = "powerpc", target_os = "linux"),
         all(target_arch = "powerpc64", target_os = "linux"),
+        any(target_arch = "x86", target_arch = "x86_64"),
     ),
     feature(stdsimd)
 )]
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5a8c9f76ea9..b22406124e0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2533,6 +2533,17 @@ pub struct FnHeader {
     pub ext: Extern,
 }
 
+impl FnHeader {
+    /// Does this function header have any qualifiers or is it empty?
+    pub fn has_qualifiers(&self) -> bool {
+        let Self { unsafety, asyncness, constness, ext } = self;
+        matches!(unsafety, Unsafety::Unsafe)
+            || asyncness.node.is_async()
+            || matches!(constness.node, Constness::Const)
+            || !matches!(ext, Extern::None)
+    }
+}
+
 impl Default for FnHeader {
     fn default() -> FnHeader {
         FnHeader {
@@ -2565,7 +2576,7 @@ pub enum ItemKind {
     /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(FnSig, Generics, P<Block>),
+    Fn(FnSig, Generics, Option<P<Block>>),
     /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
@@ -2667,7 +2678,7 @@ pub type ForeignItem = Item<ForeignItemKind>;
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum ForeignItemKind {
     /// A foreign function.
-    Fn(P<FnDecl>, Generics),
+    Fn(FnSig, Generics, Option<P<Block>>),
     /// A foreign static item (`static ext: u8`).
     Static(P<Ty>, Mutability),
     /// A foreign type.
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 3bcdf8fe286..8517f223f92 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -901,7 +901,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         ItemKind::Fn(sig, generics, body) => {
             visit_fn_sig(sig, vis);
             vis.visit_generics(generics);
-            vis.visit_block(body);
+            visit_opt(body, |body| vis.visit_block(body));
         }
         ItemKind::Mod(m) => vis.visit_mod(m),
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
@@ -1044,9 +1044,10 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     match kind {
-        ForeignItemKind::Fn(fdec, generics) => {
-            visitor.visit_fn_decl(fdec);
+        ForeignItemKind::Fn(sig, generics, body) => {
+            visit_fn_sig(sig, visitor);
             visitor.visit_generics(generics);
+            visit_opt(body, |body| visitor.visit_block(body));
         }
         ForeignItemKind::Static(t, _m) => visitor.visit_ty(t),
         ForeignItemKind::Ty => {}
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 946a0d29cd3..73e731397c3 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -19,24 +19,47 @@ use crate::tokenstream::{TokenStream, TokenTree};
 
 use rustc_span::Span;
 
+#[derive(Copy, Clone, PartialEq)]
+pub enum AssocCtxt {
+    Trait,
+    Impl,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum FnCtxt {
+    Free,
+    Foreign,
+    Assoc(AssocCtxt),
+}
+
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
-    /// E.g., `fn foo()` or `extern "Abi" fn foo()`.
-    ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
-
-    /// E.g., `fn foo(&self)`.
-    Method(Ident, &'a FnSig, &'a Visibility, &'a Block),
+    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
+    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
 
     /// E.g., `|x, y| body`.
-    Closure(&'a Expr),
+    Closure(&'a FnDecl, &'a Expr),
 }
 
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::ItemFn(_, header, _, _) => Some(header),
-            FnKind::Method(_, sig, _, _) => Some(&sig.header),
-            FnKind::Closure(_) => None,
+            FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
+            FnKind::Closure(_, _) => None,
+        }
+    }
+
+    pub fn decl(&self) -> &'a FnDecl {
+        match self {
+            FnKind::Fn(_, _, sig, _, _) => &sig.decl,
+            FnKind::Closure(decl, _) => decl,
+        }
+    }
+
+    pub fn ctxt(&self) -> Option<FnCtxt> {
+        match self {
+            FnKind::Fn(ctxt, ..) => Some(*ctxt),
+            FnKind::Closure(..) => None,
         }
     }
 }
@@ -106,17 +129,11 @@ pub trait Visitor<'ast>: Sized {
     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
         walk_where_predicate(self, p)
     }
-    fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
-        walk_fn(self, fk, fd, s)
-    }
-    fn visit_trait_item(&mut self, i: &'ast AssocItem) {
-        walk_trait_item(self, i)
+    fn visit_fn(&mut self, fk: FnKind<'ast>, s: Span, _: NodeId) {
+        walk_fn(self, fk, s)
     }
-    fn visit_impl_item(&mut self, i: &'ast AssocItem) {
-        walk_impl_item(self, i)
-    }
-    fn visit_assoc_item(&mut self, i: &'ast AssocItem) {
-        walk_assoc_item(self, i)
+    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
+        walk_assoc_item(self, i, ctxt)
     }
     fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
         walk_trait_ref(self, t)
@@ -287,13 +304,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         }
         ItemKind::Fn(ref sig, ref generics, ref body) => {
             visitor.visit_generics(generics);
-            visitor.visit_fn_header(&sig.header);
-            visitor.visit_fn(
-                FnKind::ItemFn(item.ident, &sig.header, &item.vis, body),
-                &sig.decl,
-                item.span,
-                item.id,
-            )
+            let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id)
         }
         ItemKind::Mod(ref module) => visitor.visit_mod(module, item.span, &item.attrs, item.id),
         ItemKind::ForeignMod(ref foreign_module) => {
@@ -321,17 +333,17 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_trait_ref, of_trait);
             visitor.visit_ty(self_ty);
-            walk_list!(visitor, visit_impl_item, items);
+            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
             visitor.visit_variant_data(struct_definition);
         }
-        ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
+        ItemKind::Trait(.., ref generics, ref bounds, ref items) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
+            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
         }
         ItemKind::TraitAlias(ref generics, ref bounds) => {
             visitor.visit_generics(generics);
@@ -512,21 +524,22 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
     }
 }
 
-pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a ForeignItem) {
-    visitor.visit_vis(&foreign_item.vis);
-    visitor.visit_ident(foreign_item.ident);
+pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
+    visitor.visit_vis(&item.vis);
+    visitor.visit_ident(item.ident);
 
-    match foreign_item.kind {
-        ForeignItemKind::Fn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration);
-            visitor.visit_generics(generics)
+    match item.kind {
+        ForeignItemKind::Fn(ref sig, ref generics, ref body) => {
+            visitor.visit_generics(generics);
+            let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id);
         }
         ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
         ForeignItemKind::Ty => (),
         ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
     }
 
-    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
+    walk_list!(visitor, visit_attribute, &item.attrs);
 }
 
 pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
@@ -594,37 +607,21 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
     visitor.visit_fn_ret_ty(&function_declaration.output);
 }
 
-pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
-where
-    V: Visitor<'a>,
-{
+pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
     match kind {
-        FnKind::ItemFn(_, header, _, body) => {
-            visitor.visit_fn_header(header);
-            walk_fn_decl(visitor, declaration);
-            visitor.visit_block(body);
-        }
-        FnKind::Method(_, sig, _, body) => {
+        FnKind::Fn(_, _, sig, _, body) => {
             visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, declaration);
-            visitor.visit_block(body);
+            walk_fn_decl(visitor, &sig.decl);
+            walk_list!(visitor, visit_block, body);
         }
-        FnKind::Closure(body) => {
-            walk_fn_decl(visitor, declaration);
+        FnKind::Closure(decl, body) => {
+            walk_fn_decl(visitor, decl);
             visitor.visit_expr(body);
         }
     }
 }
 
-pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
-    visitor.visit_assoc_item(item);
-}
-
-pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
-    visitor.visit_assoc_item(item);
-}
-
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
+pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.ident);
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -634,17 +631,9 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem)
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        AssocItemKind::Fn(ref sig, None) => {
-            visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, &sig.decl);
-        }
-        AssocItemKind::Fn(ref sig, Some(ref body)) => {
-            visitor.visit_fn(
-                FnKind::Method(item.ident, sig, &item.vis, body),
-                &sig.decl,
-                item.span,
-                item.id,
-            );
+        AssocItemKind::Fn(ref sig, ref body) => {
+            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id);
         }
         AssocItemKind::TyAlias(ref bounds, ref ty) => {
             walk_list!(visitor, visit_param_bound, bounds);
@@ -765,8 +754,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, _, _, ref function_declaration, ref body, _decl_span) => visitor
-            .visit_fn(FnKind::Closure(body), function_declaration, expression.span, expression.id),
+        ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => {
+            visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id)
+        }
         ExprKind::Block(ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs
index edff8bea0f3..778600b2196 100644
--- a/src/libtest/cli.rs
+++ b/src/libtest/cli.rs
@@ -1,6 +1,5 @@
 //! Module converting command-line arguments into test configuration.
 
-use getopts;
 use std::env;
 use std::path::PathBuf;
 
diff --git a/src/libtest/console.rs b/src/libtest/console.rs
index ebdfb162947..149c9202e6e 100644
--- a/src/libtest/console.rs
+++ b/src/libtest/console.rs
@@ -4,8 +4,6 @@ use std::fs::File;
 use std::io;
 use std::io::prelude::Write;
 
-use term;
-
 use super::{
     bench::fmt_bench_samples,
     cli::TestOpts,
diff --git a/src/stdarch b/src/stdarch
-Subproject e0ab2c165ace03a61139b61f1d9b86b07028850
+Subproject dea57529b3695605909e7d327bb6551d7a10c78
diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr
index 7781af89dea..6edb9e63d48 100644
--- a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr
@@ -1,6 +1,8 @@
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-63388-2.rs:12:10
    |
+LL |         foo: &dyn Foo, bar: &'a dyn Foo
+   |              --------       -----------
 LL |     ) -> &dyn Foo
    |          ^ help: consider using the named lifetime: `&'a`
    |
diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr
index 7e45d588c6c..9f51ced9c3f 100644
--- a/src/test/ui/async-await/issues/issue-63388-2.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-2.stderr
@@ -1,6 +1,8 @@
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-63388-2.rs:12:10
    |
+LL |         foo: &dyn Foo, bar: &'a dyn Foo
+   |              --------       -----------
 LL |     ) -> &dyn Foo
    |          ^ help: consider using the named lifetime: `&'a`
    |
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
index 66d0958e4c9..b4f5f9ef56b 100644
--- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.rs
@@ -1,6 +1,7 @@
 #![feature(optin_builtin_traits)]
-#![feature(overlapping_marker_traits)]
+#![feature(marker_trait_attr)]
 
+#[marker]
 trait MyTrait {}
 
 struct TestType<T>(::std::marker::PhantomData<T>);
@@ -8,11 +9,11 @@ struct TestType<T>(::std::marker::PhantomData<T>);
 unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
 
 impl<T: MyTrait> !Send for TestType<T> {}
-//~^ ERROR E0119
+//~^ ERROR conflicting implementations
 
 unsafe impl<T:'static> Send for TestType<T> {}
+//~^ ERROR conflicting implementations
 
 impl !Send for TestType<i32> {}
-//~^ ERROR E0119
 
 fn main() {}
diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
index 0a8bbc4bc50..25d3d3ee997 100644
--- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
+++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
-  --> $DIR/coherence-conflicting-negative-trait-impl.rs:10:1
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1
    |
 LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
    | ---------------------------------------------------- first implementation here
@@ -7,14 +7,14 @@ LL |
 LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
 
-error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<i32>`:
-  --> $DIR/coherence-conflicting-negative-trait-impl.rs:15:1
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `TestType<_>`:
+  --> $DIR/coherence-conflicting-negative-trait-impl.rs:14:1
    |
+LL | unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
+   | ---------------------------------------------------- first implementation here
+...
 LL | unsafe impl<T:'static> Send for TestType<T> {}
-   | ------------------------------------------- first implementation here
-LL | 
-LL | impl !Send for TestType<i32> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<i32>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/coherence/coherence-impls-send.rs b/src/test/ui/coherence/coherence-impls-send.rs
index b2a9c5be658..7898dc9831d 100644
--- a/src/test/ui/coherence/coherence-impls-send.rs
+++ b/src/test/ui/coherence/coherence-impls-send.rs
@@ -1,5 +1,4 @@
 #![feature(optin_builtin_traits)]
-#![feature(overlapping_marker_traits)]
 
 use std::marker::Copy;
 
@@ -24,7 +23,8 @@ unsafe impl Send for [MyType] {}
 //~^ ERROR E0117
 
 unsafe impl Send for &'static [NotSync] {}
-//~^ ERROR E0117
+//~^ ERROR conflicting implementations of trait
+//~| ERROR only traits defined in the current crate
 
 fn main() {
 }
diff --git a/src/test/ui/coherence/coherence-impls-send.stderr b/src/test/ui/coherence/coherence-impls-send.stderr
index a5b3c7657bd..dbfc968332c 100644
--- a/src/test/ui/coherence/coherence-impls-send.stderr
+++ b/src/test/ui/coherence/coherence-impls-send.stderr
@@ -1,5 +1,16 @@
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `&[NotSync]`:
+  --> $DIR/coherence-impls-send.rs:25:1
+   |
+LL | unsafe impl Send for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> std::marker::Send for &T
+             where T: std::marker::Sync, T: ?Sized;
+   = note: upstream crates may add a new impl of trait `std::marker::Sync` for type `[NotSync]` in future versions
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-send.rs:17:1
+  --> $DIR/coherence-impls-send.rs:16:1
    |
 LL | unsafe impl Send for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^^^^^^^^----------------
@@ -10,13 +21,13 @@ LL | unsafe impl Send for (MyType, MyType) {}
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
-  --> $DIR/coherence-impls-send.rs:20:1
+  --> $DIR/coherence-impls-send.rs:19:1
    |
 LL | unsafe impl Send for &'static NotSync {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-send.rs:23:1
+  --> $DIR/coherence-impls-send.rs:22:1
    |
 LL | unsafe impl Send for [MyType] {}
    | ^^^^^^^^^^^^^^^^^^^^^--------
@@ -27,7 +38,7 @@ LL | unsafe impl Send for [MyType] {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-send.rs:26:1
+  --> $DIR/coherence-impls-send.rs:25:1
    |
 LL | unsafe impl Send for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^------------------
@@ -37,7 +48,7 @@ LL | unsafe impl Send for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0117, E0321.
+Some errors have detailed explanations: E0117, E0119, E0321.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/consts/const-int-arithmetic.rs b/src/test/ui/consts/const-int-arithmetic.rs
new file mode 100644
index 00000000000..cfa2873c68b
--- /dev/null
+++ b/src/test/ui/consts/const-int-arithmetic.rs
@@ -0,0 +1,130 @@
+// run-pass
+
+#![feature(saturating_neg)]
+#![feature(const_checked_int_methods)]
+#![feature(const_euclidean_int_methods)]
+#![feature(const_overflowing_int_methods)]
+#![feature(const_saturating_int_methods)]
+#![feature(const_wrapping_int_methods)]
+
+use std::i8;
+
+macro_rules! suite {
+    ($(
+        $fn:ident -> $ty:ty { $( $label:ident : $expr:expr, $result:expr; )* }
+    )*) => { $(
+        fn $fn() {
+            $(
+                const $label: $ty = $expr;
+                assert_eq!($label, $result);
+            )*
+        }
+    )* }
+}
+
+suite!(
+    checked -> Option<i8> {
+        // `const_checked_int_methods`
+        C1: 5i8.checked_add(2), Some(7);
+        C2: 127i8.checked_add(2), None;
+
+        C3: 5i8.checked_sub(2), Some(3);
+        C4: (-127i8).checked_sub(2), None;
+
+        C5: 1i8.checked_mul(3), Some(3);
+        C6: 5i8.checked_mul(122), None;
+        C7: (-127i8).checked_mul(-99), None;
+
+        C8: (i8::min_value() + 1).checked_div(-1), Some(127);
+        C9: i8::min_value().checked_div(-1), None;
+        C10: 1i8.checked_div(0), None;
+
+        C11: 5i8.checked_rem(2), Some(1);
+        C12: 5i8.checked_rem(0), None;
+        C13: i8::MIN.checked_rem(-1), None;
+
+        C14: 5i8.checked_neg(), Some(-5);
+        C15: i8::MIN.checked_neg(), None;
+
+        C16: 0x1i8.checked_shl(4), Some(0x10);
+        C17: 0x1i8.checked_shl(129), None;
+
+        C18: 0x10i8.checked_shr(4), Some(0x1);
+        C19: 0x10i8.checked_shr(128), None;
+
+
+        C20: (-5i8).checked_abs(), Some(5);
+        C21: i8::MIN.checked_abs(), None;
+
+        // `const_euclidean_int_methods`
+        C22: (i8::min_value() + 1).checked_div_euclid(-1), Some(127);
+        C23: i8::min_value().checked_div_euclid(-1), None;
+        C24: (1i8).checked_div_euclid(0), None;
+
+        C25: 5i8.checked_rem_euclid(2), Some(1);
+        C26: 5i8.checked_rem_euclid(0), None;
+        C27: i8::MIN.checked_rem_euclid(-1), None;
+    }
+
+    saturating_and_wrapping -> i8 {
+        // `const_saturating_int_methods`
+        C28: 100i8.saturating_add(1), 101;
+        C29: i8::max_value().saturating_add(100), i8::max_value();
+        C30: i8::min_value().saturating_add(-1), i8::min_value();
+
+        C31: 100i8.saturating_sub(127), -27;
+        C32: i8::min_value().saturating_sub(100), i8::min_value();
+        C33: i8::max_value().saturating_sub(-1), i8::max_value();
+
+        C34: 10i8.saturating_mul(12), 120;
+        C35: i8::MAX.saturating_mul(10), i8::MAX;
+        C36: i8::MIN.saturating_mul(10), i8::MIN;
+
+        C37: 100i8.saturating_neg(), -100;
+        C38: (-100i8).saturating_neg(), 100;
+        C39: i8::min_value().saturating_neg(), i8::max_value();
+        C40: i8::max_value().saturating_neg(), i8::min_value() + 1;
+
+        C57: 100i8.saturating_abs(), 100;
+        C58: (-100i8).saturating_abs(), 100;
+        C59: i8::min_value().saturating_abs(), i8::max_value();
+        C60: (i8::min_value() + 1).saturating_abs(), i8::max_value();
+
+        // `const_wrapping_int_methods`
+        C41: 100i8.wrapping_div(10), 10;
+        C42: (-128i8).wrapping_div(-1), -128;
+
+        C43: 100i8.wrapping_rem(10), 0;
+        C44: (-128i8).wrapping_rem(-1), 0;
+
+        // `const_euclidean_int_methods`
+        C45: 100i8.wrapping_div_euclid(10), 10;
+        C46: (-128i8).wrapping_div_euclid(-1), -128;
+
+        C47: 100i8.wrapping_rem_euclid(10), 0;
+        C48: (-128i8).wrapping_rem_euclid(-1), 0;
+    }
+
+    overflowing -> (i8, bool) {
+        // `const_overflowing_int_methods`
+        C49: 5i8.overflowing_div(2), (2, false);
+        C50: i8::MIN.overflowing_div(-1), (i8::MIN, true);
+
+        C51: 5i8.overflowing_rem(2), (1, false);
+        C52: i8::MIN.overflowing_rem(-1), (0, true);
+
+        // `const_euclidean_int_methods`
+        C53: 5i8.overflowing_div_euclid(2), (2, false);
+        C54: i8::MIN.overflowing_div_euclid(-1), (i8::MIN, true);
+
+        C55: 5i8.overflowing_rem_euclid(2), (1, false);
+        C56: i8::MIN.overflowing_rem_euclid(-1), (0, true);
+
+    }
+);
+
+fn main() {
+   checked();
+   saturating_and_wrapping();
+   overflowing();
+}
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index b05b92bf1e9..fc14b7fa5b7 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -7,7 +7,7 @@ LL | fn is_send<T:Send>() { }
 LL |     is_send::<A>();
    |     ^^^^^^^^^^^^
    |
-   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit`)
    = note: required because it appears within the type `I`
    = note: required because it appears within the type `H`
    = note: required because it appears within the type `G`
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index fdbb5af9b32..e8d11530b08 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `I`
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit_deref`)
 
 error[E0308]: mismatched types
   --> $DIR/recursion_limit_deref.rs:50:22
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
index 1cc59051605..18d321c24d8 100644
--- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
@@ -7,7 +7,7 @@ LL |     ($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
 LL |     recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
    |     -------------------------------------------------- in this macro invocation
    |
-   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit_macro`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
index d06566ffbe9..01411e585ab 100644
--- a/src/test/ui/error-codes/E0055.stderr
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
 LL |     ref_foo.foo();
    |             ^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="10"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="10"]` attribute to your crate (`E0055`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr
index e01e0a6f54b..a23bcbfd71a 100644
--- a/src/test/ui/error-codes/E0106.stderr
+++ b/src/test/ui/error-codes/E0106.stderr
@@ -6,8 +6,8 @@ LL |     x: &bool,
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Foo<'lifetime> {
-LL |     x: &'lifetime bool,
+LL | struct Foo<'a> {
+LL |     x: &'a bool,
    |
 
 error[E0106]: missing lifetime specifier
@@ -18,9 +18,9 @@ LL |     B(&bool),
    |
 help: consider introducing a named lifetime parameter
    |
-LL | enum Bar<'lifetime> {
+LL | enum Bar<'a> {
 LL |     A(u8),
-LL |     B(&'lifetime bool),
+LL |     B(&'a bool),
    |
 
 error[E0106]: missing lifetime specifier
@@ -31,8 +31,8 @@ LL | type MyStr = &str;
    |
 help: consider introducing a named lifetime parameter
    |
-LL | type MyStr<'lifetime> = &'lifetime str;
-   |           ^^^^^^^^^^^   ^^^^^^^^^^
+LL | type MyStr<'a> = &'a str;
+   |           ^^^^   ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/E0106.rs:17:10
@@ -42,8 +42,8 @@ LL |     baz: Baz,
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Quux<'lifetime> {
-LL |     baz: Baz<'lifetime>,
+LL | struct Quux<'a> {
+LL |     baz: Baz<'a>,
    |
 
 error[E0106]: missing lifetime specifiers
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 1d087a46594..c551a00096e 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -7,7 +7,7 @@ LL | trait Foo {}
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`E0275`)
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/extern/extern-ffi-fn-with-body.rs b/src/test/ui/extern/extern-ffi-fn-with-body.rs
index 4cf563514ea..ef234e8afd8 100644
--- a/src/test/ui/extern/extern-ffi-fn-with-body.rs
+++ b/src/test/ui/extern/extern-ffi-fn-with-body.rs
@@ -1,5 +1,5 @@
 extern "C" {
-    fn foo() -> i32 { //~ ERROR incorrect `fn` inside `extern` block
+    fn foo() -> i32 { //~ ERROR incorrect function inside `extern` block
         return 0;
     }
 }
diff --git a/src/test/ui/extern/extern-ffi-fn-with-body.stderr b/src/test/ui/extern/extern-ffi-fn-with-body.stderr
index 4ac3ce1f93e..079c9cecd8e 100644
--- a/src/test/ui/extern/extern-ffi-fn-with-body.stderr
+++ b/src/test/ui/extern/extern-ffi-fn-with-body.stderr
@@ -1,17 +1,17 @@
-error: incorrect `fn` inside `extern` block
+error: incorrect function inside `extern` block
   --> $DIR/extern-ffi-fn-with-body.rs:2:8
    |
 LL |   extern "C" {
-   |   ------ `extern` blocks define existing foreign functions and `fn`s inside of them cannot have a body
+   |   ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
 LL |       fn foo() -> i32 {
    |  ________^^^__________-
    | |        |
-   | |        can't have a body
+   | |        cannot have a body
 LL | |         return 0;
 LL | |     }
-   | |_____- this body is invalid here
+   | |_____- help: remove the invalid body: `;`
    |
-   = help: you might have meant to write a function accessible through ffi, which can be done by writing `extern fn` outside of the `extern` block
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
 error: aborting due to previous error
diff --git a/src/test/ui/generic/generic-extern-lifetime.stderr b/src/test/ui/generic/generic-extern-lifetime.stderr
index 39372c93158..72951aea4aa 100644
--- a/src/test/ui/generic/generic-extern-lifetime.stderr
+++ b/src/test/ui/generic/generic-extern-lifetime.stderr
@@ -9,12 +9,24 @@ error[E0261]: use of undeclared lifetime name `'a`
    |
 LL |    pub fn life4<'b>(x: for<'c> fn(&'a i32));
    |                                    ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL |    pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
+   |                              ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/generic-extern-lifetime.rs:11:38
    |
 LL |    pub fn life7<'b>() -> for<'c> fn(&'a i32);
    |                                      ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL |    pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
+   |                                ^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
index 14c53f90665..211a3286cc3 100644
--- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr
@@ -6,8 +6,8 @@ LL |     type Output = &i32;
    |
 help: consider introducing a named lifetime parameter
    |
-LL |     type Output<'lifetime> = &'lifetime i32;
-   |                ^^^^^^^^^^^   ^^^^^^^^^^
+LL |     type Output<'a> = &'a i32;
+   |                ^^^^   ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/assoc-type.rs:16:20
@@ -17,8 +17,8 @@ LL |     type Output = &'_ i32;
    |
 help: consider introducing a named lifetime parameter
    |
-LL |     type Output<'lifetime> = &'lifetime i32;
-   |                ^^^^^^^^^^^    ^^^^^^^^^
+LL |     type Output<'a> = &'a i32;
+   |                ^^^^    ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
index 5f101a24c1d..f2a4150632d 100644
--- a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
+++ b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
@@ -6,8 +6,8 @@ LL | struct Heartbreak(Betrayal);
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Heartbreak<'lifetime>(Betrayal<'lifetime>);
-   |                  ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
+LL | struct Heartbreak<'a>(Betrayal<'a>);
+   |                  ^^^^ ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
index bfb20ade035..a43b49041ec 100644
--- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
+++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr
@@ -11,6 +11,16 @@ error[E0261]: use of undeclared lifetime name `'test`
    |
 LL |     let y: fn(&'test u32) = foo2;
    |                ^^^^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider introducing lifetime `'test` here
+   |
+LL | fn bar<'test>() {
+   |       ^^^^^^^
+help: consider making the type lifetime-generic with a new `'test` lifetime
+   |
+LL |     let y: for<'test> fn(&'test u32) = foo2;
+   |            ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index 8c59fbd5301..e7d90f00d24 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -13,7 +13,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
 LL |     Foo.foo;
    |     ^^^^^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
   --> $DIR/infinite-autoderef.rs:25:9
@@ -21,7 +21,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
 LL |     Foo.foo;
    |         ^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0609]: no field `foo` on type `Foo`
   --> $DIR/infinite-autoderef.rs:25:9
@@ -35,7 +35,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
 LL |     Foo.bar();
    |         ^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0599]: no method named `bar` found for struct `Foo` in the current scope
   --> $DIR/infinite-autoderef.rs:26:9
diff --git a/src/test/ui/infinite/infinite-macro-expansion.stderr b/src/test/ui/infinite/infinite-macro-expansion.stderr
index 159312e5c1b..ff67eea5688 100644
--- a/src/test/ui/infinite/infinite-macro-expansion.stderr
+++ b/src/test/ui/infinite/infinite-macro-expansion.stderr
@@ -7,7 +7,7 @@ LL |     () => (recursive!())
 LL |     recursive!()
    |     ------------ in this macro invocation
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_macro_expansion`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/issues/issue-16098.stderr
index 2b9657d4628..a34039a6eec 100644
--- a/src/test/ui/issues/issue-16098.stderr
+++ b/src/test/ui/issues/issue-16098.stderr
@@ -7,7 +7,7 @@ LL |             $n + prob1!($n - 1);
 LL |     println!("Problem 1: {}", prob1!(1000));
    |                               ------------ in this macro invocation
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_16098`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/issues/issue-18400.stderr
index 85cfa5663f1..57067ad5175 100644
--- a/src/test/ui/issues/issue-18400.stderr
+++ b/src/test/ui/issues/issue-18400.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
 LL |     0.contains(bits);
    |       ^^^^^^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_18400`)
    = note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}`
    = note: required because of the requirements on the impl of `Set<&[&[_]]>` for `{integer}`
    = note: required because of the requirements on the impl of `Set<&[&[&[_]]]>` for `{integer}`
diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr
index 8a627bc0bd4..337f2f971ed 100644
--- a/src/test/ui/issues/issue-19707.stderr
+++ b/src/test/ui/issues/issue-19707.stderr
@@ -2,25 +2,35 @@ error[E0106]: missing lifetime specifier
   --> $DIR/issue-19707.rs:3:28
    |
 LL | type Foo = fn(&u8, &u8) -> &u8;
-   |                            ^ expected named lifetime parameter
+   |               ---  ---     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8;
+   |            ^^^^^^^    ^^^^^^  ^^^^^^     ^^^
 help: consider introducing a named lifetime parameter
    |
-LL | type Foo<'lifetime> = fn(&u8, &u8) -> &'lifetime u8;
-   |         ^^^^^^^^^^^                   ^^^^^^^^^^
+LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8;
+   |         ^^^^      ^^^^^^  ^^^^^^     ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-19707.rs:5:27
    |
 LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
-   |                           ^ expected named lifetime parameter
+   |              ---  ---     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | fn bar<F: for<'a> Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
+   |           ^^^^^^^    ^^^^^^  ^^^^^^     ^^^
 help: consider introducing a named lifetime parameter
    |
-LL | fn bar<'lifetime, F: Fn(&u8, &u8) -> &'lifetime u8>(f: &F) {}
-   |        ^^^^^^^^^^                    ^^^^^^^^^^
+LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {}
+   |        ^^^       ^^^^^^  ^^^^^^     ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index e765144ff0b..84e64ff74ae 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -15,7 +15,7 @@ LL | trait Foo {
 LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
@@ -153,7 +153,7 @@ LL | trait Foo {
 LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index d2c1421e29e..7625e30498a 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 LL | impl<T: Next> Next for GetNext<T> {
    |               ^^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
    = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
 error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
@@ -13,7 +13,7 @@ error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
    = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
index 85d5d9cc42e..1d8fbdc63c5 100644
--- a/src/test/ui/issues/issue-26638.stderr
+++ b/src/test/ui/issues/issue-26638.stderr
@@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:1:62
    |
 LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-   |                                                              ^ expected named lifetime parameter
+   |                     ------------------------------------     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
 help: consider introducing a named lifetime parameter
    |
-LL | fn parse_type<'lifetime>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'lifetime str { iter.next() }
-   |              ^^^^^^^^^^^                                                ^^^^^^^^^^
+LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
+   |              ^^^^                                                ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:4:40
diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr
index c9402277640..ab43d4a3c60 100644
--- a/src/test/ui/issues/issue-30255.stderr
+++ b/src/test/ui/issues/issue-30255.stderr
@@ -2,37 +2,37 @@ error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:9:24
    |
 LL | fn f(a: &S, b: i32) -> &i32 {
-   |                        ^ expected named lifetime parameter
+   |         --             ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
 help: consider introducing a named lifetime parameter
    |
-LL | fn f<'lifetime>(a: &S, b: i32) -> &'lifetime i32 {
-   |     ^^^^^^^^^^^                   ^^^^^^^^^^
+LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 {
+   |     ^^^^    ^^^^^             ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:14:34
    |
 LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
-   |                                  ^ expected named lifetime parameter
+   |         --              ----     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
 help: consider introducing a named lifetime parameter
    |
-LL | fn g<'lifetime>(a: &S, b: bool, c: &i32) -> &'lifetime i32 {
-   |     ^^^^^^^^^^^                             ^^^^^^^^^^
+LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 {
+   |     ^^^^    ^^^^^              ^^^^^^^     ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-30255.rs:19:44
    |
 LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
-   |                                            ^ expected named lifetime parameter
+   |         -----              --     ----     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
 help: consider introducing a named lifetime parameter
    |
-LL | fn h<'lifetime>(a: &bool, b: bool, c: &S, d: &i32) -> &'lifetime i32 {
-   |     ^^^^^^^^^^^                                       ^^^^^^^^^^
+LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 {
+   |     ^^^^    ^^^^^^^^              ^^^^^     ^^^^^^^     ^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/issues/issue-38940.stderr
index f60387f841a..36117278fd8 100644
--- a/src/test/ui/issues/issue-38940.stderr
+++ b/src/test/ui/issues/issue-38940.stderr
@@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `I`
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`issue_38940`)
 
 error[E0308]: mismatched types
   --> $DIR/issue-38940.rs:43:22
diff --git a/src/test/ui/issues/issue-39616.rs b/src/test/ui/issues/issue-39616.rs
index 3d8e28e5c2f..428856a36b4 100644
--- a/src/test/ui/issues/issue-39616.rs
+++ b/src/test/ui/issues/issue-39616.rs
@@ -1,5 +1,4 @@
 fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
-//~| ERROR expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
-// FIXME(jseyfried): avoid emitting the second error (preexisting)
+//~| ERROR expected `;` or `{`, found `]`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-39616.stderr b/src/test/ui/issues/issue-39616.stderr
index 74e94eda51f..ced58274661 100644
--- a/src/test/ui/issues/issue-39616.stderr
+++ b/src/test/ui/issues/issue-39616.stderr
@@ -4,11 +4,11 @@ error: expected type, found `0`
 LL | fn foo(a: [0; 1]) {}
    |            ^ expected type
 
-error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
+error: expected `;` or `{`, found `]`
   --> $DIR/issue-39616.rs:1:16
    |
 LL | fn foo(a: [0; 1]) {}
-   |                ^ expected one of `)`, `,`, `->`, `where`, or `{`
+   |                ^ expected `;` or `{`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
index 1d5eeac23f9..461c1832e9a 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
@@ -10,25 +10,25 @@ error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33
    |
 LL | fn g(_x: &isize, _y: &isize) -> &isize {
-   |                                 ^ expected named lifetime parameter
+   |          ------      ------     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
 help: consider introducing a named lifetime parameter
    |
-LL | fn g<'lifetime>(_x: &isize, _y: &isize) -> &'lifetime isize {
-   |     ^^^^^^^^^^^                            ^^^^^^^^^^
+LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize {
+   |     ^^^^     ^^^^^^^^^      ^^^^^^^^^     ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19
    |
 LL | fn h(_x: &Foo) -> &isize {
-   |                   ^ expected named lifetime parameter
+   |          ----     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
 help: consider introducing a named lifetime parameter
    |
-LL | fn h<'lifetime>(_x: &Foo) -> &'lifetime isize {
-   |     ^^^^^^^^^^^              ^^^^^^^^^^
+LL | fn h<'a>(_x: &'a Foo) -> &'a isize {
+   |     ^^^^     ^^^^^^^     ^^^
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
index 2990ab86824..c1fcab2409f 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr
@@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
   --> $DIR/ex1b-return-no-names-if-else.rs:1:29
    |
 LL | fn foo(x: &i32, y: &i32) -> &i32 {
-   |                             ^ expected named lifetime parameter
+   |           ----     ----     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
 help: consider introducing a named lifetime parameter
    |
-LL | fn foo<'lifetime>(x: &i32, y: &i32) -> &'lifetime i32 {
-   |       ^^^^^^^^^^^                      ^^^^^^^^^^
+LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
+   |       ^^^^    ^^^^^^^     ^^^^^^^     ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs
index 4e8339a8e6b..5ce1f576081 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.rs
+++ b/src/test/ui/lint/lint-unnecessary-parens.rs
@@ -38,6 +38,9 @@ macro_rules! baz {
     }
 }
 
+const CONST_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value
+static STATIC_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value
+
 fn main() {
     foo();
     bar((true)); //~ ERROR unnecessary parentheses around function argument
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
index 3663f1d98bb..8858c953273 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.stderr
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -34,26 +34,38 @@ error: unnecessary parentheses around block return value
 LL |     (5)
    |     ^^^ help: remove these parentheses
 
+error: unnecessary parentheses around assigned value
+  --> $DIR/lint-unnecessary-parens.rs:41:27
+   |
+LL | const CONST_ITEM: usize = (10);
+   |                           ^^^^ help: remove these parentheses
+
+error: unnecessary parentheses around assigned value
+  --> $DIR/lint-unnecessary-parens.rs:42:29
+   |
+LL | static STATIC_ITEM: usize = (10);
+   |                             ^^^^ help: remove these parentheses
+
 error: unnecessary parentheses around function argument
-  --> $DIR/lint-unnecessary-parens.rs:43:9
+  --> $DIR/lint-unnecessary-parens.rs:46:9
    |
 LL |     bar((true));
    |         ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `if` condition
-  --> $DIR/lint-unnecessary-parens.rs:45:8
+  --> $DIR/lint-unnecessary-parens.rs:48:8
    |
 LL |     if (true) {}
    |        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `while` condition
-  --> $DIR/lint-unnecessary-parens.rs:46:11
+  --> $DIR/lint-unnecessary-parens.rs:49:11
    |
 LL |     while (true) {}
    |           ^^^^^^ help: remove these parentheses
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/lint-unnecessary-parens.rs:46:5
+  --> $DIR/lint-unnecessary-parens.rs:49:5
    |
 LL |     while (true) {}
    |     ^^^^^^^^^^^^ help: use `loop`
@@ -61,46 +73,46 @@ LL |     while (true) {}
    = note: `#[warn(while_true)]` on by default
 
 error: unnecessary parentheses around `match` head expression
-  --> $DIR/lint-unnecessary-parens.rs:48:11
+  --> $DIR/lint-unnecessary-parens.rs:51:11
    |
 LL |     match (true) {
    |           ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:51:16
+  --> $DIR/lint-unnecessary-parens.rs:54:16
    |
 LL |     if let 1 = (1) {}
    |                ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around `let` head expression
-  --> $DIR/lint-unnecessary-parens.rs:52:19
+  --> $DIR/lint-unnecessary-parens.rs:55:19
    |
 LL |     while let 1 = (2) {}
    |                   ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around method argument
-  --> $DIR/lint-unnecessary-parens.rs:66:24
+  --> $DIR/lint-unnecessary-parens.rs:69:24
    |
 LL |     X { y: false }.foo((true));
    |                        ^^^^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:68:18
+  --> $DIR/lint-unnecessary-parens.rs:71:18
    |
 LL |     let mut _a = (0);
    |                  ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:69:10
+  --> $DIR/lint-unnecessary-parens.rs:72:10
    |
 LL |     _a = (0);
    |          ^^^ help: remove these parentheses
 
 error: unnecessary parentheses around assigned value
-  --> $DIR/lint-unnecessary-parens.rs:70:11
+  --> $DIR/lint-unnecessary-parens.rs:73:11
    |
 LL |     _a += (1);
    |           ^^^ help: remove these parentheses
 
-error: aborting due to 15 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr
index 1139ef06a12..92d1afe1b64 100644
--- a/src/test/ui/macros/issue-54441.stderr
+++ b/src/test/ui/macros/issue-54441.stderr
@@ -1,8 +1,8 @@
-error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found keyword `let`
+error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `static`, `type`, or `unsafe`, found keyword `let`
   --> $DIR/issue-54441.rs:3:9
    |
 LL |         let
-   |         ^^^ expected one of `crate`, `fn`, `pub`, `static`, or `type`
+   |         ^^^ expected one of 9 possible tokens
 ...
 LL |     m!();
    |     ----- in this macro invocation
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
index 4e86daffb61..021c51fd726 100644
--- a/src/test/ui/macros/trace_faulty_macros.stderr
+++ b/src/test/ui/macros/trace_faulty_macros.stderr
@@ -29,7 +29,7 @@ LL |         my_recursive_macro!();
 LL |     my_recursive_macro!();
    |     ---------------------- in this macro invocation
    |
-   = help: consider adding a `#![recursion_limit="8"]` attribute to your crate
+   = help: consider adding a `#![recursion_limit="8"]` attribute to your crate (`trace_faulty_macros`)
 
 note: trace_macro
   --> $DIR/trace_faulty_macros.rs:34:5
diff --git a/src/test/ui/no-patterns-in-args-2.rs b/src/test/ui/no-patterns-in-args-2.rs
index ccf57478b48..85b7fc5cdba 100644
--- a/src/test/ui/no-patterns-in-args-2.rs
+++ b/src/test/ui/no-patterns-in-args-2.rs
@@ -1,9 +1,9 @@
 #![deny(patterns_in_fns_without_body)]
 
 trait Tr {
-    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+    fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in functions without bodies
                         //~^ WARN was previously accepted
-    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
+    fn f2(&arg: u8); //~ ERROR patterns aren't allowed in functions without bodies
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     #[allow(anonymous_parameters)]
diff --git a/src/test/ui/no-patterns-in-args-2.stderr b/src/test/ui/no-patterns-in-args-2.stderr
index 905a89af4e5..21f4439d890 100644
--- a/src/test/ui/no-patterns-in-args-2.stderr
+++ b/src/test/ui/no-patterns-in-args-2.stderr
@@ -1,10 +1,10 @@
-error[E0642]: patterns aren't allowed in methods without bodies
+error[E0642]: patterns aren't allowed in functions without bodies
   --> $DIR/no-patterns-in-args-2.rs:6:11
    |
 LL |     fn f2(&arg: u8);
-   |           ^^^^
+   |           ^^^^ pattern not allowed in function without body
 
-error: patterns aren't allowed in methods without bodies
+error: patterns aren't allowed in functions without bodies
   --> $DIR/no-patterns-in-args-2.rs:4:11
    |
 LL |     fn f1(mut arg: u8);
diff --git a/src/test/ui/no-patterns-in-args-macro.rs b/src/test/ui/no-patterns-in-args-macro.rs
index 59cb9945398..b5109f9c286 100644
--- a/src/test/ui/no-patterns-in-args-macro.rs
+++ b/src/test/ui/no-patterns-in-args-macro.rs
@@ -6,10 +6,10 @@ macro_rules! m {
 
         type A = fn($pat: u8);
 
-        extern {
+        extern "C" {
             fn foreign_fn($pat: u8);
         }
-    }
+    };
 }
 
 mod good_pat {
@@ -20,7 +20,7 @@ mod bad_pat {
     m!((bad, pat));
     //~^ ERROR patterns aren't allowed in function pointer types
     //~| ERROR patterns aren't allowed in foreign function declarations
-    //~| ERROR patterns aren't allowed in methods without bodies
+    //~| ERROR patterns aren't allowed in functions without bodies
 }
 
 fn main() {}
diff --git a/src/test/ui/no-patterns-in-args-macro.stderr b/src/test/ui/no-patterns-in-args-macro.stderr
index f21df68d5a2..0016c7953f3 100644
--- a/src/test/ui/no-patterns-in-args-macro.stderr
+++ b/src/test/ui/no-patterns-in-args-macro.stderr
@@ -1,8 +1,8 @@
-error[E0642]: patterns aren't allowed in methods without bodies
+error[E0642]: patterns aren't allowed in functions without bodies
   --> $DIR/no-patterns-in-args-macro.rs:20:8
    |
 LL |     m!((bad, pat));
-   |        ^^^^^^^^^^
+   |        ^^^^^^^^^^ pattern not allowed in function without body
 
 error[E0561]: patterns aren't allowed in function pointer types
   --> $DIR/no-patterns-in-args-macro.rs:20:8
diff --git a/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs b/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs
new file mode 100644
index 00000000000..1a65a1e544b
--- /dev/null
+++ b/src/test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(or_patterns)]
+
+enum MyEnum {
+    FirstCase(u8),
+    OtherCase(u16),
+}
+
+fn my_fn(x @ (MyEnum::FirstCase(_) | MyEnum::OtherCase(_)): MyEnum) {}
+
+fn main() {
+    my_fn(MyEnum::FirstCase(0));
+}
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
index 3d4069f368d..dd09d68367e 100644
--- a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
+++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
@@ -1,8 +1,9 @@
 // run-pass
 
-#![feature(overlapping_marker_traits)]
+#![feature(marker_trait_attr)]
 #![feature(specialization)]
 
+#[marker]
 trait MyMarker {}
 
 impl<T> MyMarker for T {}
diff --git a/src/test/ui/overlap-marker-trait.rs b/src/test/ui/overlap-marker-trait.rs
deleted file mode 100644
index bf39d9c903f..00000000000
--- a/src/test/ui/overlap-marker-trait.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Test for RFC 1268: we allow overlapping impls of marker traits,
-// that is, traits without items. In this case, a type `T` is
-// `MyMarker` if it is either `Debug` or `Display`. This test just
-// checks that we don't consider **all** types to be `MyMarker`.  See
-// also the companion test in
-// `run-pass/overlap-permitted-for-marker-traits.rs`.
-
-#![feature(overlapping_marker_traits)]
-#![feature(optin_builtin_traits)]
-
-use std::fmt::{Debug, Display};
-
-trait Marker {}
-
-impl<T: Debug> Marker for T {}
-impl<T: Display> Marker for T {}
-
-fn is_marker<T: Marker>() { }
-
-struct NotDebugOrDisplay;
-
-fn main() {
-    // Debug && Display:
-    is_marker::<i32>();
-
-    // Debug && !Display:
-    is_marker::<Vec<i32>>();
-
-    // !Debug && !Display
-    is_marker::<NotDebugOrDisplay>(); //~ ERROR
-}
diff --git a/src/test/ui/overlap-marker-trait.stderr b/src/test/ui/overlap-marker-trait.stderr
deleted file mode 100644
index 15ebcd17b0d..00000000000
--- a/src/test/ui/overlap-marker-trait.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
-  --> $DIR/overlap-marker-trait.rs:30:17
-   |
-LL | fn is_marker<T: Marker>() { }
-   |    ---------    ------ required by this bound in `is_marker`
-...
-LL |     is_marker::<NotDebugOrDisplay>();
-   |                 ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index bb17e97e950..a8f0b7d61b9 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -1,4 +1,4 @@
-// error-pattern:expected one of `(`, `fn`, `static`, or `type`
+// error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn`
 extern {
     pub pub fn foo();
 }
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 313e88e812b..cba4058e482 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,8 +1,8 @@
-error: expected one of `(`, `fn`, `static`, or `type`, found keyword `pub`
+error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub`
   --> $DIR/duplicate-visibility.rs:3:9
    |
 LL |     pub pub fn foo();
-   |         ^^^ expected one of `(`, `fn`, `static`, or `type`
+   |         ^^^ expected one of 8 possible tokens
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/fn-body-optional-semantic-fail.rs b/src/test/ui/parser/fn-body-optional-semantic-fail.rs
new file mode 100644
index 00000000000..38def05e8f2
--- /dev/null
+++ b/src/test/ui/parser/fn-body-optional-semantic-fail.rs
@@ -0,0 +1,27 @@
+// Tests the different rules for `fn` forms requiring the presence or lack of a body.
+
+fn main() {
+    fn f1(); //~ ERROR free function without a body
+    fn f2() {} // OK.
+
+    trait X {
+        fn f1(); // OK.
+        fn f2() {} // OK.
+    }
+
+    struct Y;
+    impl X for Y {
+        fn f1(); //~ ERROR associated function in `impl` without body
+        fn f2() {} // OK.
+    }
+
+    impl Y {
+        fn f3(); //~ ERROR associated function in `impl` without body
+        fn f4() {} // OK.
+    }
+
+    extern {
+        fn f5(); // OK.
+        fn f6() {} //~ ERROR incorrect function inside `extern` block
+    }
+}
diff --git a/src/test/ui/parser/fn-body-optional-semantic-fail.stderr b/src/test/ui/parser/fn-body-optional-semantic-fail.stderr
new file mode 100644
index 00000000000..23ce98fb5d7
--- /dev/null
+++ b/src/test/ui/parser/fn-body-optional-semantic-fail.stderr
@@ -0,0 +1,40 @@
+error: free function without a body
+  --> $DIR/fn-body-optional-semantic-fail.rs:4:5
+   |
+LL |     fn f1();
+   |     ^^^^^^^-
+   |            |
+   |            help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+  --> $DIR/fn-body-optional-semantic-fail.rs:14:9
+   |
+LL |         fn f1();
+   |         ^^^^^^^-
+   |                |
+   |                help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+  --> $DIR/fn-body-optional-semantic-fail.rs:19:9
+   |
+LL |         fn f3();
+   |         ^^^^^^^-
+   |                |
+   |                help: provide a definition for the function: `{ <body> }`
+
+error: incorrect function inside `extern` block
+  --> $DIR/fn-body-optional-semantic-fail.rs:25:12
+   |
+LL |     extern {
+   |     ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |         fn f5(); // OK.
+LL |         fn f6() {}
+   |            ^^   -- help: remove the invalid body: `;`
+   |            |
+   |            cannot have a body
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/fn-body-optional-syntactic-pass.rs b/src/test/ui/parser/fn-body-optional-syntactic-pass.rs
new file mode 100644
index 00000000000..e7991c73b4b
--- /dev/null
+++ b/src/test/ui/parser/fn-body-optional-syntactic-pass.rs
@@ -0,0 +1,31 @@
+// Ensures that all `fn` forms having or lacking a body are syntactically valid.
+
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    fn f();
+    fn f() {}
+
+    trait X {
+        fn f();
+        fn f() {}
+    }
+
+    impl X for Y {
+        fn f();
+        fn f() {}
+    }
+
+    impl Y {
+        fn f();
+        fn f() {}
+    }
+
+    extern {
+        fn f();
+        fn f() {}
+    }
+}
diff --git a/src/test/ui/parser/fn-header-semantic-fail.rs b/src/test/ui/parser/fn-header-semantic-fail.rs
new file mode 100644
index 00000000000..c2b7e69c80d
--- /dev/null
+++ b/src/test/ui/parser/fn-header-semantic-fail.rs
@@ -0,0 +1,57 @@
+// Ensures that all `fn` forms can have all the function qualifiers syntactically.
+
+// edition:2018
+
+#![feature(const_extern_fn)]
+#![feature(const_fn)]
+
+fn main() {
+    async fn ff1() {} // OK.
+    unsafe fn ff2() {} // OK.
+    const fn ff3() {} // OK.
+    extern "C" fn ff4() {} // OK.
+    const /* async */ unsafe extern "C" fn ff5() {} // OK.
+    //^ FIXME(Centril): `async` should be legal syntactically, ensure it's illegal semantically.
+
+    trait X {
+        async fn ft1(); //~ ERROR trait fns cannot be declared `async`
+        unsafe fn ft2(); // OK.
+        const fn ft3(); //~ ERROR trait fns cannot be declared const
+        extern "C" fn ft4(); // OK.
+        /* const */ async unsafe extern "C" fn ft5();
+        //~^ ERROR trait fns cannot be declared `async`
+        //^ FIXME(Centril): `const` should be legal syntactically, ensure it's illegal semantically.
+    }
+
+    struct Y;
+    impl X for Y {
+        async fn ft1() {} //~ ERROR trait fns cannot be declared `async`
+        //~^ ERROR method `ft1` has an incompatible type for trait
+        unsafe fn ft2() {} // OK.
+        const fn ft3() {} //~ ERROR trait fns cannot be declared const
+        extern "C" fn ft4() {}
+        /* const */ async unsafe extern "C" fn ft5() {}
+        //~^ ERROR trait fns cannot be declared `async`
+        //~| ERROR method `ft5` has an incompatible type for trait
+        //^ FIXME(Centril): `const` should be legal syntactically, ensure it's illegal semantically.
+    }
+
+    impl Y {
+        async fn fi1() {} // OK.
+        unsafe fn fi2() {} // OK.
+        const fn fi3() {} // OK.
+        extern "C" fn fi4() {} // OK.
+        /* const */ async unsafe extern "C" fn fi5() {} // OK.
+        //^ FIXME(Centril): `const` should be legal syntactically, ensure it's illegal semantically.
+    }
+
+    extern {
+        async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers
+        unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers
+        const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
+        extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers
+        /* const */ async unsafe extern "C" fn fe5();
+        //~^ ERROR functions in `extern` blocks cannot have qualifiers
+        //^ FIXME(Centril): `const` should be legal syntactically, ensure it's illegal semantically.
+    }
+}
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
new file mode 100644
index 00000000000..41d2d9b7faa
--- /dev/null
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -0,0 +1,136 @@
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:17:9
+   |
+LL |         async fn ft1();
+   |         ^^^^^^^^^^^^^^^
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/fn-header-semantic-fail.rs:19:9
+   |
+LL |         const fn ft3();
+   |         ^^^^^ trait fns cannot be const
+
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:21:21
+   |
+LL |         /* const */ async unsafe extern "C" fn ft5();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:28:9
+   |
+LL |         async fn ft1() {}
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/fn-header-semantic-fail.rs:31:9
+   |
+LL |         const fn ft3() {}
+   |         ^^^^^ trait fns cannot be const
+
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/fn-header-semantic-fail.rs:33:21
+   |
+LL |         /* const */ async unsafe extern "C" fn ft5() {}
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:49:18
+   |
+LL |     extern {
+   |     ------ in this `extern` block
+LL |         async fn fe1();
+   |         ---------^^^
+   |         |
+   |         help: remove the qualifiers: `fn`
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:50:19
+   |
+LL |     extern {
+   |     ------ in this `extern` block
+LL |         async fn fe1();
+LL |         unsafe fn fe2();
+   |         ----------^^^
+   |         |
+   |         help: remove the qualifiers: `fn`
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:51:18
+   |
+LL |     extern {
+   |     ------ in this `extern` block
+...
+LL |         const fn fe3();
+   |         ---------^^^
+   |         |
+   |         help: remove the qualifiers: `fn`
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:52:23
+   |
+LL |     extern {
+   |     ------ in this `extern` block
+...
+LL |         extern "C" fn fe4();
+   |         --------------^^^
+   |         |
+   |         help: remove the qualifiers: `fn`
+
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/fn-header-semantic-fail.rs:53:48
+   |
+LL |     extern {
+   |     ------ in this `extern` block
+...
+LL |         /* const */ async unsafe extern "C" fn fe5();
+   |                     ---------------------------^^^
+   |                     |
+   |                     help: remove the qualifiers: `fn`
+
+error[E0053]: method `ft1` has an incompatible type for trait
+  --> $DIR/fn-header-semantic-fail.rs:28:24
+   |
+LL |         async fn ft1();
+   |                       - type in trait
+...
+LL |         async fn ft1() {}
+   |                        ^
+   |                        |
+   |                        the `Output` of this `async fn`'s found opaque type
+   |                        expected `()`, found opaque type
+   |
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn() -> impl std::future::Future`
+
+error[E0053]: method `ft5` has an incompatible type for trait
+  --> $DIR/fn-header-semantic-fail.rs:33:54
+   |
+LL |         /* const */ async unsafe extern "C" fn ft5();
+   |                                                     - type in trait
+...
+LL |         /* const */ async unsafe extern "C" fn ft5() {}
+   |                                                      ^
+   |                                                      |
+   |                                                      the `Output` of this `async fn`'s found opaque type
+   |                                                      expected `()`, found opaque type
+   |
+   = note: expected fn pointer `unsafe extern "C" fn()`
+              found fn pointer `unsafe extern "C" fn() -> impl std::future::Future`
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0053, E0379, E0706.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/parser/fn-header-syntactic-pass.rs b/src/test/ui/parser/fn-header-syntactic-pass.rs
new file mode 100644
index 00000000000..145a208cb24
--- /dev/null
+++ b/src/test/ui/parser/fn-header-syntactic-pass.rs
@@ -0,0 +1,55 @@
+// Ensures that all `fn` forms can have all the function qualifiers syntactically.
+
+// check-pass
+// edition:2018
+
+#![feature(const_extern_fn)]
+//^ FIXME(Centril): move check to ast_validation.
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    async fn f();
+    unsafe fn f();
+    const fn f();
+    extern "C" fn f();
+    const /* async */ unsafe extern "C" fn f();
+    //^ FIXME(Centril): `async` should be legal syntactically.
+
+    trait X {
+        async fn f();
+        unsafe fn f();
+        const fn f();
+        extern "C" fn f();
+        /* const */ async unsafe extern "C" fn f();
+        //^ FIXME(Centril): `const` should be legal syntactically.
+    }
+
+    impl X for Y {
+        async fn f();
+        unsafe fn f();
+        const fn f();
+        extern "C" fn f();
+        /* const */ async unsafe extern "C" fn f();
+        //^ FIXME(Centril): `const` should be legal syntactically.
+    }
+
+    impl Y {
+        async fn f();
+        unsafe fn f();
+        const fn f();
+        extern "C" fn f();
+        /* const */ async unsafe extern "C" fn f();
+        //^ FIXME(Centril): `const` should be legal syntactically.
+    }
+
+    extern {
+        async fn f();
+        unsafe fn f();
+        const fn f();
+        extern "C" fn f();
+        /* const */ async unsafe extern "C" fn f();
+        //^ FIXME(Centril): `const` should be legal syntactically.
+    }
+}
diff --git a/src/test/ui/parser/issue-24780.rs b/src/test/ui/parser/issue-24780.rs
index 799cdd80222..8b46aa2bf22 100644
--- a/src/test/ui/parser/issue-24780.rs
+++ b/src/test/ui/parser/issue-24780.rs
@@ -3,6 +3,6 @@
 // expected one of ..., `>`, ... found `>`
 
 fn foo() -> Vec<usize>> {
-    //~^ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
+    //~^ ERROR expected `;` or `{`, found `>`
     Vec::new()
 }
diff --git a/src/test/ui/parser/issue-24780.stderr b/src/test/ui/parser/issue-24780.stderr
index d9470191b25..d65a5f44873 100644
--- a/src/test/ui/parser/issue-24780.stderr
+++ b/src/test/ui/parser/issue-24780.stderr
@@ -1,8 +1,8 @@
-error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
+error: expected `;` or `{`, found `>`
   --> $DIR/issue-24780.rs:5:23
    |
 LL | fn foo() -> Vec<usize>> {
-   |                       ^ expected one of `!`, `+`, `::`, `where`, or `{`
+   |                       ^ expected `;` or `{`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-63135.rs b/src/test/ui/parser/issue-63135.rs
index d5f5f1469f3..7d46b8904f0 100644
--- a/src/test/ui/parser/issue-63135.rs
+++ b/src/test/ui/parser/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 6 previous errors
+// error-pattern: aborting due to 7 previous errors
 
 fn i(n{...,f #
diff --git a/src/test/ui/parser/issue-63135.stderr b/src/test/ui/parser/issue-63135.stderr
index 462fdf11f40..04afae93be0 100644
--- a/src/test/ui/parser/issue-63135.stderr
+++ b/src/test/ui/parser/issue-63135.stderr
@@ -43,5 +43,11 @@ error: expected one of `:` or `|`, found `)`
 LL | fn i(n{...,f #
    |                ^ expected one of `:` or `|`
 
-error: aborting due to 6 previous errors
+error: expected `;` or `{`, found `<eof>`
+  --> $DIR/issue-63135.rs:3:16
+   |
+LL | fn i(n{...,f #
+   |                ^ expected `;` or `{`
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/parser/issue-68788-in-trait-item-propagation.rs b/src/test/ui/parser/issue-68788-in-trait-item-propagation.rs
new file mode 100644
index 00000000000..7c3dd1d5a98
--- /dev/null
+++ b/src/test/ui/parser/issue-68788-in-trait-item-propagation.rs
@@ -0,0 +1,21 @@
+// Make sure we don't propagate restrictions on trait impl items to items inside them.
+
+// check-pass
+// edition:2018
+
+fn main() {}
+
+trait X {
+    fn foo();
+}
+
+impl X for () {
+    fn foo() {
+        struct S;
+        impl S {
+            pub const X: u8 = 0;
+            pub const fn bar() {}
+            async fn qux() {}
+        }
+    }
+}
diff --git a/src/test/ui/parser/missing_right_paren.rs b/src/test/ui/parser/missing_right_paren.rs
index c35236ce793..810dee9571d 100644
--- a/src/test/ui/parser/missing_right_paren.rs
+++ b/src/test/ui/parser/missing_right_paren.rs
@@ -1,3 +1,3 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: aborting due to 4 previous errors
 fn main((ؼ
\ No newline at end of file
diff --git a/src/test/ui/parser/missing_right_paren.stderr b/src/test/ui/parser/missing_right_paren.stderr
index d67e7c88912..c1ceb81a07c 100644
--- a/src/test/ui/parser/missing_right_paren.stderr
+++ b/src/test/ui/parser/missing_right_paren.stderr
@@ -22,5 +22,11 @@ error: expected one of `:` or `|`, found `)`
 LL | fn main((ؼ
    |           ^ expected one of `:` or `|`
 
-error: aborting due to 3 previous errors
+error: expected `;` or `{`, found `<eof>`
+  --> $DIR/missing_right_paren.rs:3:11
+   |
+LL | fn main((ؼ
+   |           ^ expected `;` or `{`
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.rs b/src/test/ui/parser/no-const-fn-in-extern-block.rs
index 29f26389ded..4cae703a163 100644
--- a/src/test/ui/parser/no-const-fn-in-extern-block.rs
+++ b/src/test/ui/parser/no-const-fn-in-extern-block.rs
@@ -1,8 +1,8 @@
 extern {
     const fn foo();
-    //~^ ERROR extern items cannot be `const`
+    //~^ ERROR functions in `extern` blocks cannot have qualifiers
     const unsafe fn bar();
-    //~^ ERROR extern items cannot be `const`
+    //~^ ERROR functions in `extern` blocks cannot have qualifiers
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.stderr b/src/test/ui/parser/no-const-fn-in-extern-block.stderr
index 5b4663a702f..de653987e40 100644
--- a/src/test/ui/parser/no-const-fn-in-extern-block.stderr
+++ b/src/test/ui/parser/no-const-fn-in-extern-block.stderr
@@ -1,14 +1,23 @@
-error: extern items cannot be `const`
-  --> $DIR/no-const-fn-in-extern-block.rs:2:5
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/no-const-fn-in-extern-block.rs:2:14
    |
+LL | extern {
+   | ------ in this `extern` block
 LL |     const fn foo();
-   |     ^^^^^
+   |     ---------^^^
+   |     |
+   |     help: remove the qualifiers: `fn`
 
-error: extern items cannot be `const`
-  --> $DIR/no-const-fn-in-extern-block.rs:4:5
+error: functions in `extern` blocks cannot have qualifiers
+  --> $DIR/no-const-fn-in-extern-block.rs:4:21
    |
+LL | extern {
+   | ------ in this `extern` block
+...
 LL |     const unsafe fn bar();
-   |     ^^^^^
+   |     ----------------^^^
+   |     |
+   |     help: remove the qualifiers: `fn`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/not-a-pred.stderr b/src/test/ui/parser/not-a-pred.stderr
index 90246b92bf0..dce54655fa0 100644
--- a/src/test/ui/parser/not-a-pred.stderr
+++ b/src/test/ui/parser/not-a-pred.stderr
@@ -1,8 +1,8 @@
-error: expected one of `->`, `where`, or `{`, found `:`
+error: expected `;` or `{`, found `:`
   --> $DIR/not-a-pred.rs:3:26
    |
 LL | fn f(a: isize, b: isize) : lt(a, b) { }
-   |                          ^ expected one of `->`, `where`, or `{`
+   |                          ^ expected `;` or `{`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/proc-macro/auxiliary/issue-59191.rs b/src/test/ui/proc-macro/auxiliary/issue-59191.rs
new file mode 100644
index 00000000000..d9ee77067ec
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/issue-59191.rs
@@ -0,0 +1,16 @@
+// edition:2018
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn no_main(_attrs: TokenStream, _input: TokenStream) -> TokenStream {
+    let new_krate = r#"
+        fn main() {}
+    "#;
+    new_krate.parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs
new file mode 100644
index 00000000000..a59cacb8bde
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs
@@ -0,0 +1,8 @@
+// edition:2018
+// aux-crate:issue_59191=issue-59191.rs
+// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely.
+// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`.
+#![feature(custom_inner_attributes)]
+//~^ ERROR `main` function not found in crate `issue_59191_replace_root_with_fn` [E0601]
+#![issue_59191::no_main]
+//~^ ERROR expected crate top-level item to be a module after macro expansion, found a function
diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
new file mode 100644
index 00000000000..e0a3caef9db
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
@@ -0,0 +1,17 @@
+error: expected crate top-level item to be a module after macro expansion, found a function
+  --> $DIR/issue-59191-replace-root-with-fn.rs:7:1
+   |
+LL | #![issue_59191::no_main]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0601]: `main` function not found in crate `issue_59191_replace_root_with_fn`
+  --> $DIR/issue-59191-replace-root-with-fn.rs:5:1
+   |
+LL | / #![feature(custom_inner_attributes)]
+LL | |
+LL | | #![issue_59191::no_main]
+   | |________________________^ consider adding a `main` function to `$DIR/issue-59191-replace-root-with-fn.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr
index 01eadbe252e..27f7639d213 100644
--- a/src/test/ui/proc-macro/item-error.stderr
+++ b/src/test/ui/proc-macro/item-error.stderr
@@ -6,8 +6,8 @@ LL |     a: &u64
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct A<'lifetime> {
-LL |     a: &'lifetime u64
+LL | struct A<'a> {
+LL |     a: &'a u64
    |
 
 error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-in-enums-anon.stderr b/src/test/ui/regions/regions-in-enums-anon.stderr
index 41655a210b3..b3649c5b485 100644
--- a/src/test/ui/regions/regions-in-enums-anon.stderr
+++ b/src/test/ui/regions/regions-in-enums-anon.stderr
@@ -6,8 +6,8 @@ LL |     Bar(&isize)
    |
 help: consider introducing a named lifetime parameter
    |
-LL | enum Foo<'lifetime> {
-LL |     Bar(&'lifetime isize)
+LL | enum Foo<'a> {
+LL |     Bar(&'a isize)
    |
 
 error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-in-structs-anon.stderr b/src/test/ui/regions/regions-in-structs-anon.stderr
index fbe8036880f..60a6fb9a0fa 100644
--- a/src/test/ui/regions/regions-in-structs-anon.stderr
+++ b/src/test/ui/regions/regions-in-structs-anon.stderr
@@ -6,8 +6,8 @@ LL |     x: &isize
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Foo<'lifetime> {
-LL |     x: &'lifetime isize
+LL | struct Foo<'a> {
+LL |     x: &'a isize
    |
 
 error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr
index 79ebef41dcc..eb19a30c52b 100644
--- a/src/test/ui/regions/regions-name-undeclared.stderr
+++ b/src/test/ui/regions/regions-name-undeclared.stderr
@@ -88,12 +88,32 @@ error[E0261]: use of undeclared lifetime name `'b`
    |
 LL | ...                   &'b isize,
    |                        ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider introducing lifetime `'b` here
+   |
+LL | fn fn_types<'b>(a: &'a isize,
+   |            ^^^^
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |             b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
+   |                              ^^^^
 
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/regions-name-undeclared.rs:45:36
    |
 LL | ...                   &'b isize)>,
    |                        ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider introducing lifetime `'b` here
+   |
+LL | fn fn_types<'b>(a: &'a isize,
+   |            ^^^^
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL |             b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
+   |                              ^^^^
 
 error[E0261]: use of undeclared lifetime name `'a`
   --> $DIR/regions-name-undeclared.rs:46:17
diff --git a/src/test/ui/rfc1623-2.rs b/src/test/ui/rfc1623-2.rs
new file mode 100644
index 00000000000..35a2ef10c2e
--- /dev/null
+++ b/src/test/ui/rfc1623-2.rs
@@ -0,0 +1,13 @@
+#![allow(dead_code)]
+
+fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
+    a
+}
+
+// the boundaries of elision
+static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+//~^ ERROR missing lifetime specifier [E0106]
+    &(non_elidable as fn(&u8, &u8) -> &u8);
+    //~^ ERROR missing lifetime specifier [E0106]
+
+fn main() {}
diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr
new file mode 100644
index 00000000000..732bb61e6ee
--- /dev/null
+++ b/src/test/ui/rfc1623-2.stderr
@@ -0,0 +1,29 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/rfc1623-2.rs:8:42
+   |
+LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
+   |                             ---  ---     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
+   |                          ^^^^^^^    ^^^^^^  ^^^^^^     ^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/rfc1623-2.rs:10:39
+   |
+LL |     &(non_elidable as fn(&u8, &u8) -> &u8);
+   |                          ---  ---     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL |     &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
+   |                       ^^^^^^^    ^^^^^^  ^^^^^^     ^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs
index ebb4d56af9e..55f5d0b94dc 100644
--- a/src/test/ui/rfc1623.rs
+++ b/src/test/ui/rfc1623.rs
@@ -4,11 +4,10 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
     a
 }
 
-// the boundaries of elision
-static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
-//~^ ERROR missing lifetime specifier [E0106]
-    &(non_elidable as fn(&u8, &u8) -> &u8);
-    //~^ ERROR missing lifetime specifier [E0106]
+// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs`
+static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
+    &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
+
 
 struct SomeStruct<'x, 'y, 'z: 'x> {
     foo: &'x Foo<'z>,
@@ -20,10 +19,12 @@ fn id<T>(t: T) -> T {
     t
 }
 
-static SOME_STRUCT: &SomeStruct = SomeStruct {
+static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types
     foo: &Foo { bools: &[false, true] },
     bar: &Bar { bools: &[true, true] },
     f: &id,
+    //~^ ERROR type mismatch in function arguments
+    //~| ERROR type mismatch resolving
 };
 
 // very simple test for a 'static static with default lifetime
diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr
index 5b665e18141..ca956004ef7 100644
--- a/src/test/ui/rfc1623.stderr
+++ b/src/test/ui/rfc1623.stderr
@@ -1,19 +1,46 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/rfc1623.rs:8:42
+error[E0308]: mismatched types
+  --> $DIR/rfc1623.rs:22:35
    |
-LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
-   |                                          ^ expected named lifetime parameter
+LL |   static SOME_STRUCT: &SomeStruct = SomeStruct {
+   |  ___________________________________^
+LL | |     foo: &Foo { bools: &[false, true] },
+LL | |     bar: &Bar { bools: &[true, true] },
+LL | |     f: &id,
+LL | |
+LL | |
+LL | | };
+   | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct`
    |
-   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+help: consider borrowing here
+   |
+LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
+LL |     foo: &Foo { bools: &[false, true] },
+LL |     bar: &Bar { bools: &[true, true] },
+LL |     f: &id,
+LL |
+LL |
+ ...
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/rfc1623.rs:25:8
+   |
+LL | fn id<T>(t: T) -> T {
+   | ------------------- found signature of `fn(_) -> _`
+...
+LL |     f: &id,
+   |        ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _`
+   |
+   = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/rfc1623.rs:10:39
+error[E0271]: type mismatch resolving `for<'a, 'b> <fn(_) -> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>`
+  --> $DIR/rfc1623.rs:25:8
    |
-LL |     &(non_elidable as fn(&u8, &u8) -> &u8);
-   |                                       ^ expected named lifetime parameter
+LL |     f: &id,
+   |        ^^^ expected bound lifetime parameter 'a, found concrete lifetime
    |
-   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0106`.
+Some errors have detailed explanations: E0271, E0308, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs b/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs
new file mode 100644
index 00000000000..dac6610b335
--- /dev/null
+++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.rs
@@ -0,0 +1,8 @@
+struct S1<F: Fn(&i32, &i32) -> &'a i32>(F); //~ ERROR use of undeclared lifetime name `'a`
+struct S2<F: Fn(&i32, &i32) -> &i32>(F); //~ ERROR missing lifetime specifier
+struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
+struct S4<F: for<'x> Fn(&'x i32, &'x i32) -> &'x i32>(F);
+const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
+//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear
+fn main() {}
diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
new file mode 100644
index 00000000000..fe9c3445fc4
--- /dev/null
+++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr
@@ -0,0 +1,49 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/fn-missing-lifetime-in-item.rs:1:33
+   |
+LL | struct S1<F: Fn(&i32, &i32) -> &'a i32>(F);
+   |                                 ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider introducing lifetime `'a` here
+   |
+LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
+   |           ^^^
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+   |              ^^^^^^^
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/fn-missing-lifetime-in-item.rs:2:32
+   |
+LL | struct S2<F: Fn(&i32, &i32) -> &i32>(F);
+   |                 ----  ----     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | struct S2<F: for<'a> Fn(&'a i32, &'a i32) -> &'a i32>(F);
+   |              ^^^^^^^    ^^^^^^^  ^^^^^^^     ^^^
+help: consider introducing a named lifetime parameter
+   |
+LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F);
+   |           ^^^       ^^^^^^^  ^^^^^^^     ^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/fn-missing-lifetime-in-item.rs:3:40
+   |
+LL | struct S3<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+   |                                        ^^^^^^^
+
+error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/fn-missing-lifetime-in-item.rs:6:55
+   |
+LL | const C: Option<Box<dyn for<'a> Fn(&usize, &usize) -> &'a usize>> = None;
+   |                                                       ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0106, E0261, E0582.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs
new file mode 100644
index 00000000000..22dc448c97f
--- /dev/null
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.rs
@@ -0,0 +1,2 @@
+fn f(_: impl Iterator<Item = &'_ ()>) {} //~ ERROR missing lifetime specifier
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr
new file mode 100644
index 00000000000..e31f25ab603
--- /dev/null
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-trait-missing-lifetime.rs:1:31
+   |
+LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
+   |                               ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
+   |     ^^^^                          ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/suggestions/return-without-lifetime.stderr b/src/test/ui/suggestions/return-without-lifetime.stderr
index 7f5ff95938e..ce3b1748da4 100644
--- a/src/test/ui/suggestions/return-without-lifetime.stderr
+++ b/src/test/ui/suggestions/return-without-lifetime.stderr
@@ -8,7 +8,7 @@ error[E0106]: missing lifetime specifier
   --> $DIR/return-without-lifetime.rs:5:34
    |
 LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
-   |                                  ^ help: consider using the named lifetime: `&'a`
+   |                    ---------     ^ help: consider using the named lifetime: `&'a`
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
 
@@ -16,7 +16,7 @@ error[E0106]: missing lifetime specifier
   --> $DIR/return-without-lifetime.rs:7:35
    |
 LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
-   |                                   ^ help: consider using the named lifetime: `&'a`
+   |                    ----------     ^ help: consider using the named lifetime: `&'a`
    |
    = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
 
diff --git a/src/test/ui/suggestions/suggest-split-at-mut.rs b/src/test/ui/suggestions/suggest-split-at-mut.rs
new file mode 100644
index 00000000000..d294c20b824
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-split-at-mut.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let mut foo = [1, 2, 3, 4];
+    let a = &mut foo[2];
+    let b = &mut foo[3]; //~ ERROR cannot borrow `foo[_]` as mutable more than once at a time
+    *a = 5;
+    *b = 6;
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/suggestions/suggest-split-at-mut.stderr b/src/test/ui/suggestions/suggest-split-at-mut.stderr
new file mode 100644
index 00000000000..330f012b2a9
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-split-at-mut.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time
+  --> $DIR/suggest-split-at-mut.rs:4:13
+   |
+LL |     let a = &mut foo[2];
+   |             ----------- first mutable borrow occurs here
+LL |     let b = &mut foo[3];
+   |             ^^^^^^^^^^^ second mutable borrow occurs here
+LL |     *a = 5;
+   |     ------ first borrow later used here
+   |
+   = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/super-fast-paren-parsing.rs b/src/test/ui/super-fast-paren-parsing.rs
index 60c8db53a8c..cb42ff2c644 100644
--- a/src/test/ui/super-fast-paren-parsing.rs
+++ b/src/test/ui/super-fast-paren-parsing.rs
@@ -1,5 +1,6 @@
 // run-pass
 
+#![allow(unused_parens)]
 #![allow(non_upper_case_globals)]
 #![allow(dead_code)]
 // exec-env:RUST_MIN_STACK=16000000
diff --git a/src/test/ui/traits/overlap-permitted-for-marker-traits-neg.rs b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs
index bc8dc8dbd05..86029473b51 100644
--- a/src/test/ui/traits/overlap-permitted-for-marker-traits-neg.rs
+++ b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.rs
@@ -1,12 +1,11 @@
-// run-pass
 #![allow(dead_code)]
-#![feature(overlapping_marker_traits)]
 #![feature(optin_builtin_traits)]
 
-// Overlapping negative impls for `MyStruct` are permitted:
+// Overlapping negative impls for `MyStruct` are not permitted:
 struct MyStruct;
 impl !Send for MyStruct {}
 impl !Send for MyStruct {}
+//~^ ERROR conflicting implementations of trait
 
 fn main() {
 }
diff --git a/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr
new file mode 100644
index 00000000000..94a0c287f4a
--- /dev/null
+++ b/src/test/ui/traits/overlap-not-permitted-for-builtin-trait.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `std::marker::Send` for type `MyStruct`:
+  --> $DIR/overlap-not-permitted-for-builtin-trait.rs:7:1
+   |
+LL | impl !Send for MyStruct {}
+   | ----------------------- first implementation here
+LL | impl !Send for MyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/overlap-permitted-for-marker-traits.rs b/src/test/ui/traits/overlap-permitted-for-marker-traits.rs
deleted file mode 100644
index 59ec9d5689d..00000000000
--- a/src/test/ui/traits/overlap-permitted-for-marker-traits.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// run-pass
-// Tests for RFC 1268: we allow overlapping impls of marker traits,
-// that is, traits without items. In this case, a type `T` is
-// `MyMarker` if it is either `Debug` or `Display`.
-
-#![feature(overlapping_marker_traits)]
-#![feature(optin_builtin_traits)]
-
-use std::fmt::{Debug, Display};
-
-trait MyMarker {}
-
-impl<T: Debug> MyMarker for T {}
-impl<T: Display> MyMarker for T {}
-
-fn foo<T: MyMarker>(t: T) -> T {
-    t
-}
-
-fn main() {
-    // Debug && Display:
-    assert_eq!(1, foo(1));
-    assert_eq!(2.0, foo(2.0));
-
-    // Debug && !Display:
-    assert_eq!(vec![1], foo(vec![1]));
-}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
index 0a028e44919..1719a99d421 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr
@@ -2,12 +2,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39
    |
 LL |     let _: dyn Foo(&isize, &usize) -> &usize;
-   |                                       ^ expected named lifetime parameter
+   |                    ------  ------     ^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
 help: consider introducing a named lifetime parameter
    |
-LL | fn main<'lifetime>() {
+LL | fn main<'a>() {
 LL |     eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>,
 LL |           dyn Foo(&isize) -> &isize                                   >();
 LL |     eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
index 04df2e45703..fe242e6a909 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
@@ -6,8 +6,8 @@ LL |     x: Box<dyn Debug + '_>,
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Foo<'lifetime> {
-LL |     x: Box<dyn Debug + 'lifetime>,
+LL | struct Foo<'a> {
+LL |     x: Box<dyn Debug + 'a>,
    |
 
 error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
index cf820249c80..8d2c82e59ed 100644
--- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
+++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr
@@ -2,13 +2,13 @@ error[E0106]: missing lifetime specifier
   --> $DIR/in-fn-return-illegal.rs:5:30
    |
 LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
-   |                              ^^ expected named lifetime parameter
+   |           ----     ----      ^^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
 help: consider introducing a named lifetime parameter
    |
-LL | fn foo<'lifetime>(x: &u32, y: &u32) -> &'lifetime u32 { loop { } }
-   |       ^^^^^^^^^^^                       ^^^^^^^^^
+LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } }
+   |       ^^^^    ^^^^^^^     ^^^^^^^      ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/in-struct.stderr b/src/test/ui/underscore-lifetime/in-struct.stderr
index e01b39a4b64..4275cc26f73 100644
--- a/src/test/ui/underscore-lifetime/in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/in-struct.stderr
@@ -6,8 +6,8 @@ LL |     x: &'_ u32,
    |
 help: consider introducing a named lifetime parameter
    |
-LL | struct Foo<'lifetime> {
-LL |     x: &'lifetime u32,
+LL | struct Foo<'a> {
+LL |     x: &'a u32,
    |
 
 error[E0106]: missing lifetime specifier
@@ -18,8 +18,8 @@ LL |     Variant(&'_ u32),
    |
 help: consider introducing a named lifetime parameter
    |
-LL | enum Bar<'lifetime> {
-LL |     Variant(&'lifetime u32),
+LL | enum Bar<'a> {
+LL |     Variant(&'a u32),
    |
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
index 517904ee628..c7cda38e476 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
@@ -28,13 +28,13 @@ error[E0106]: missing lifetime specifier
   --> $DIR/underscore-lifetime-binders.rs:16:35
    |
 LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
-   |                                   ^^ expected named lifetime parameter
+   |            ------     ------      ^^ expected named lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
 help: consider introducing a named lifetime parameter
    |
-LL | fn foo2<'lifetime>(_: &'_ u8, y: &'_ u8) -> &'lifetime u8 { y }
-   |        ^^^^^^^^^^^                           ^^^^^^^^^
+LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y }
+   |        ^^^^    ^^^^^^     ^^^^^^      ^^
 
 error: aborting due to 5 previous errors