about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-10-30 08:09:59 +0000
committerbors <bors@rust-lang.org>2022-10-30 08:09:59 +0000
commite96c330af5e3baebe7a80999744e2e082b279d0a (patch)
tree141684e5cad5a8a16a6c23aab8d4ac2c5dca0f9d
parentb03502b35d111bef0399a66ab3cc765f0802e8ba (diff)
parentdf74f07b18925c4a5330255f84d8162d9e40c1ed (diff)
downloadrust-e96c330af5e3baebe7a80999744e2e082b279d0a.tar.gz
rust-e96c330af5e3baebe7a80999744e2e082b279d0a.zip
Auto merge of #103755 - Dylan-DPC:rollup-dl2hups, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #93582 (Allow `impl Fn() -> impl Trait` in return position)
 - #103560 (Point only to the identifiers in the typo suggestions of shadowed names instead of the entire struct)
 - #103588 (rustdoc: add missing URL redirect)
 - #103689 (Do fewer passes and generally be more efficient when filtering tests)
 - #103740 (rustdoc: remove unnecessary CSS `.search-results { padding-bottom }`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs16
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs45
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs36
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/test/src/console.rs6
-rw-r--r--library/test/src/event.rs2
-rw-r--r--library/test/src/lib.rs87
-rw-r--r--src/doc/rustdoc/book.toml4
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr15
-rw-r--r--src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs8
-rw-r--r--src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr11
-rw-r--r--src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs24
-rw-r--r--src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr51
-rw-r--r--src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs15
-rw-r--r--src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr26
-rw-r--r--src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs15
-rw-r--r--src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr24
-rw-r--r--src/test/ui/impl-trait/impl_fn_associativity.rs26
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.rs4
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.stderr22
-rw-r--r--src/test/ui/impl-trait/where-allowed.rs7
-rw-r--r--src/test/ui/impl-trait/where-allowed.stderr98
-rw-r--r--src/test/ui/lexical-scopes.stderr2
-rw-r--r--src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr16
-rw-r--r--src/test/ui/span/issue-35987.stderr3
30 files changed, 435 insertions, 152 deletions
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 888776cccac..c6955741fd4 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -191,7 +191,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
                 GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
-                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Ok => {
+                        self.lower_parenthesized_parameter_data(data, itctx)
+                    }
                     ParenthesizedGenericArgs::Err => {
                         // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
                         let sub = if !data.inputs.is_empty() {
@@ -344,6 +346,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_parenthesized_parameter_data(
         &mut self,
         data: &ParenthesizedArgs,
+        itctx: &ImplTraitContext,
     ) -> (GenericArgsCtor<'hir>, bool) {
         // Switch to `PassThrough` mode for anonymous lifetimes; this
         // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -355,6 +358,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
         }));
         let output_ty = match output {
+            // Only allow `impl Trait` in return position. i.e.:
+            // ```rust
+            // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
+            // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
+            // ```
+            FnRetTy::Ty(ty)
+                if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
+                    && self.tcx.features().impl_trait_in_fn_trait_return =>
+            {
+                self.lower_ty(&ty, itctx)
+            }
             FnRetTy::Ty(ty) => {
                 self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
             }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 4facb6140a3..96645d40086 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -412,6 +412,8 @@ declare_features! (
     (active, half_open_range_patterns_in_slices, "CURRENT_RUSTC_VERSION", Some(67264), None),
     /// Allows `if let` guard in match arms.
     (active, if_let_guard, "1.47.0", Some(51114), None),
+    /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
+    (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None),
     /// Allows using imported `main` function
     (active, imported_main, "1.53.0", Some(28937), None),
     /// Allows associated types in inherent impls.
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 5d868ebec94..5029c339963 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -58,16 +58,32 @@ pub(crate) enum SuggestionTarget {
 #[derive(Debug)]
 pub(crate) struct TypoSuggestion {
     pub candidate: Symbol,
+    /// The source location where the name is defined; None if the name is not defined
+    /// in source e.g. primitives
+    pub span: Option<Span>,
     pub res: Res,
     pub target: SuggestionTarget,
 }
 
 impl TypoSuggestion {
-    pub(crate) fn typo_from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
-        Self { candidate, res, target: SuggestionTarget::SimilarlyNamed }
+    pub(crate) fn typo_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
+        Self {
+            candidate: ident.name,
+            span: Some(ident.span),
+            res,
+            target: SuggestionTarget::SimilarlyNamed,
+        }
+    }
+    pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
+        Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
     }
-    pub(crate) fn single_item_from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
-        Self { candidate, res, target: SuggestionTarget::SingleItem }
+    pub(crate) fn single_item_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
+        Self {
+            candidate: ident.name,
+            span: Some(ident.span),
+            res,
+            target: SuggestionTarget::SingleItem,
+        }
     }
 }
 
@@ -490,7 +506,7 @@ impl<'a> Resolver<'a> {
             if let Some(binding) = resolution.borrow().binding {
                 let res = binding.res();
                 if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
-                    names.push(TypoSuggestion::typo_from_res(key.ident.name, res));
+                    names.push(TypoSuggestion::typo_from_ident(key.ident, res));
                 }
             }
         }
@@ -1145,7 +1161,7 @@ impl<'a> Resolver<'a> {
                                 .get(&expn_id)
                                 .into_iter()
                                 .flatten()
-                                .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)),
+                                .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
                         );
                     }
                 }
@@ -1164,7 +1180,7 @@ impl<'a> Resolver<'a> {
                                 suggestions.extend(
                                     ext.helper_attrs
                                         .iter()
-                                        .map(|name| TypoSuggestion::typo_from_res(*name, res)),
+                                        .map(|name| TypoSuggestion::typo_from_name(*name, res)),
                                 );
                             }
                         }
@@ -1174,8 +1190,8 @@ impl<'a> Resolver<'a> {
                     if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
                         let res = macro_rules_binding.binding.res();
                         if filter_fn(res) {
-                            suggestions.push(TypoSuggestion::typo_from_res(
-                                macro_rules_binding.ident.name,
+                            suggestions.push(TypoSuggestion::typo_from_ident(
+                                macro_rules_binding.ident,
                                 res,
                             ))
                         }
@@ -1193,7 +1209,7 @@ impl<'a> Resolver<'a> {
                     suggestions.extend(this.macro_use_prelude.iter().filter_map(
                         |(name, binding)| {
                             let res = binding.res();
-                            filter_fn(res).then_some(TypoSuggestion::typo_from_res(*name, res))
+                            filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
                         },
                     ));
                 }
@@ -1203,14 +1219,14 @@ impl<'a> Resolver<'a> {
                         suggestions.extend(
                             BUILTIN_ATTRIBUTES
                                 .iter()
-                                .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)),
+                                .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
                         );
                     }
                 }
                 Scope::ExternPrelude => {
                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
                         let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
-                        filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res))
+                        filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
                     }));
                 }
                 Scope::ToolPrelude => {
@@ -1218,7 +1234,7 @@ impl<'a> Resolver<'a> {
                     suggestions.extend(
                         this.registered_tools
                             .iter()
-                            .map(|ident| TypoSuggestion::typo_from_res(ident.name, res)),
+                            .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
                     );
                 }
                 Scope::StdLibPrelude => {
@@ -1235,7 +1251,8 @@ impl<'a> Resolver<'a> {
                 Scope::BuiltinTypes => {
                     suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
                         let res = Res::PrimTy(*prim_ty);
-                        filter_fn(res).then_some(TypoSuggestion::typo_from_res(prim_ty.name(), res))
+                        filter_fn(res)
+                            .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
                     }))
                 }
             }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 7d5fe32ee28..103187b00d1 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -150,7 +150,7 @@ struct BaseError {
 #[derive(Debug)]
 enum TypoCandidate {
     Typo(TypoSuggestion),
-    Shadowed(Res),
+    Shadowed(Res, Option<Span>),
     None,
 }
 
@@ -158,7 +158,7 @@ impl TypoCandidate {
     fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
         match self {
             TypoCandidate::Typo(sugg) => Some(sugg),
-            TypoCandidate::Shadowed(_) | TypoCandidate::None => None,
+            TypoCandidate::Shadowed(_, _) | TypoCandidate::None => None,
         }
     }
 }
@@ -691,9 +691,20 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         let is_expected = &|res| source.is_expected(res);
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
         let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
-        if let TypoCandidate::Shadowed(res) = typo_sugg
-            && let Some(id) = res.opt_def_id()
-            && let Some(sugg_span) = self.r.opt_span(id)
+        let is_in_same_file = &|sp1, sp2| {
+            let source_map = self.r.session.source_map();
+            let file1 = source_map.span_to_filename(sp1);
+            let file2 = source_map.span_to_filename(sp2);
+            file1 == file2
+        };
+        // print 'you might have meant' if the candidate is (1) is a shadowed name with
+        // accessible definition and (2) either defined in the same crate as the typo
+        // (could be in a different file) or introduced in the same file as the typo
+        // (could belong to a different crate)
+        if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
+            && res
+                .opt_def_id()
+                .map_or(false, |id| id.is_local() || is_in_same_file(span, sugg_span))
         {
             err.span_label(
                 sugg_span,
@@ -970,10 +981,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         .collect();
                 if targets.len() == 1 {
                     let target = targets[0];
-                    return Some(TypoSuggestion::single_item_from_res(
-                        target.0.ident.name,
-                        target.1,
-                    ));
+                    return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1));
                 }
             }
         }
@@ -1615,7 +1623,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 // Locals and type parameters
                 for (ident, &res) in &rib.bindings {
                     if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
-                        names.push(TypoSuggestion::typo_from_res(ident.name, res));
+                        names.push(TypoSuggestion::typo_from_ident(*ident, res));
                     }
                 }
 
@@ -1644,9 +1652,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                                             Res::Def(DefKind::Mod, crate_id.as_def_id());
 
                                         if filter_fn(crate_mod) {
-                                            Some(TypoSuggestion::typo_from_res(
-                                                ident.name, crate_mod,
-                                            ))
+                                            Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
                                         } else {
                                             None
                                         }
@@ -1665,7 +1671,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             // Add primitive types to the mix
             if filter_fn(Res::PrimTy(PrimTy::Bool)) {
                 names.extend(PrimTy::ALL.iter().map(|prim_ty| {
-                    TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty))
+                    TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty))
                 }))
             }
         } else {
@@ -1692,7 +1698,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     return TypoCandidate::None;
                 };
                 if found == name {
-                    TypoCandidate::Shadowed(sugg.res)
+                    TypoCandidate::Shadowed(sugg.res, sugg.span)
                 } else {
                     TypoCandidate::Typo(sugg)
                 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7f16da52b44..7e565df7601 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -813,6 +813,7 @@ symbols! {
         impl_lint_pass,
         impl_macros,
         impl_trait_in_bindings,
+        impl_trait_in_fn_trait_return,
         implied_by,
         import,
         import_name_type,
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index b1270c27271..8cb88016b23 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -228,9 +228,9 @@ fn on_test_event(
     out: &mut dyn OutputFormatter,
 ) -> io::Result<()> {
     match (*event).clone() {
-        TestEvent::TeFiltered(ref filtered_tests, shuffle_seed) => {
-            st.total = filtered_tests.len();
-            out.write_run_start(filtered_tests.len(), shuffle_seed)?;
+        TestEvent::TeFiltered(filtered_tests, shuffle_seed) => {
+            st.total = filtered_tests;
+            out.write_run_start(filtered_tests, shuffle_seed)?;
         }
         TestEvent::TeFilteredOut(filtered_out) => {
             st.filtered_out = filtered_out;
diff --git a/library/test/src/event.rs b/library/test/src/event.rs
index 6ff1a615eb4..80281ebd2d4 100644
--- a/library/test/src/event.rs
+++ b/library/test/src/event.rs
@@ -28,7 +28,7 @@ impl CompletedTest {
 
 #[derive(Debug, Clone)]
 pub enum TestEvent {
-    TeFiltered(Vec<TestDesc>, Option<u64>),
+    TeFiltered(usize, Option<u64>),
     TeWait(TestDesc),
     TeResult(CompletedTest),
     TeTimeout(TestDesc),
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 141f16d17f0..56a8d92f55d 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -219,6 +219,35 @@ pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
     }
 }
 
+struct FilteredTests {
+    tests: Vec<(TestId, TestDescAndFn)>,
+    benchs: Vec<(TestId, TestDescAndFn)>,
+    next_id: usize,
+}
+
+impl FilteredTests {
+    fn add_bench(&mut self, desc: TestDesc, testfn: TestFn) {
+        let test = TestDescAndFn { desc, testfn };
+        self.benchs.push((TestId(self.next_id), test));
+        self.next_id += 1;
+    }
+    fn add_test(&mut self, desc: TestDesc, testfn: TestFn) {
+        let test = TestDescAndFn { desc, testfn };
+        self.tests.push((TestId(self.next_id), test));
+        self.next_id += 1;
+    }
+    fn add_bench_as_test(
+        &mut self,
+        desc: TestDesc,
+        benchfn: impl Fn(&mut Bencher) -> Result<(), String> + Send + 'static,
+    ) {
+        let testfn = DynTestFn(Box::new(move || {
+            bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
+        }));
+        self.add_test(desc, testfn);
+    }
+}
+
 pub fn run_tests<F>(
     opts: &TestOpts,
     tests: Vec<TestDescAndFn>,
@@ -247,45 +276,51 @@ where
 
     let tests_len = tests.len();
 
-    let mut filtered_tests = filter_tests(opts, tests);
-    if !opts.bench_benchmarks {
-        filtered_tests = convert_benchmarks_to_tests(filtered_tests);
-    }
+    let mut filtered = FilteredTests { tests: Vec::new(), benchs: Vec::new(), next_id: 0 };
 
-    let filtered_tests = {
-        let mut filtered_tests = filtered_tests;
-        for test in filtered_tests.iter_mut() {
-            test.desc.name = test.desc.name.with_padding(test.testfn.padding());
-        }
+    for test in filter_tests(opts, tests) {
+        let mut desc = test.desc;
+        desc.name = desc.name.with_padding(test.testfn.padding());
 
-        filtered_tests
-    };
+        match test.testfn {
+            DynBenchFn(benchfn) => {
+                if opts.bench_benchmarks {
+                    filtered.add_bench(desc, DynBenchFn(benchfn));
+                } else {
+                    filtered.add_bench_as_test(desc, benchfn);
+                }
+            }
+            StaticBenchFn(benchfn) => {
+                if opts.bench_benchmarks {
+                    filtered.add_bench(desc, StaticBenchFn(benchfn));
+                } else {
+                    filtered.add_bench_as_test(desc, benchfn);
+                }
+            }
+            testfn => {
+                filtered.add_test(desc, testfn);
+            }
+        };
+    }
 
-    let filtered_out = tests_len - filtered_tests.len();
+    let filtered_out = tests_len - filtered.tests.len();
     let event = TestEvent::TeFilteredOut(filtered_out);
     notify_about_test_event(event)?;
 
-    let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect();
-
     let shuffle_seed = get_shuffle_seed(opts);
 
-    let event = TestEvent::TeFiltered(filtered_descs, shuffle_seed);
+    let event = TestEvent::TeFiltered(filtered.tests.len(), shuffle_seed);
     notify_about_test_event(event)?;
 
-    let (mut filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
-        .into_iter()
-        .enumerate()
-        .map(|(i, e)| (TestId(i), e))
-        .partition(|(_, e)| matches!(e.testfn, StaticTestFn(_) | DynTestFn(_)));
-
     let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
 
+    let mut remaining = filtered.tests;
     if let Some(shuffle_seed) = shuffle_seed {
-        shuffle_tests(shuffle_seed, &mut filtered_tests);
+        shuffle_tests(shuffle_seed, &mut remaining);
     }
     // Store the tests in a VecDeque so we can efficiently remove the first element to run the
     // tests in the order they were passed (unless shuffled).
-    let mut remaining = VecDeque::from(filtered_tests);
+    let mut remaining = VecDeque::from(remaining);
     let mut pending = 0;
 
     let (tx, rx) = channel::<CompletedTest>();
@@ -402,7 +437,7 @@ where
 
     if opts.bench_benchmarks {
         // All benchmarks run at the end, in serial.
-        for (id, b) in filtered_benchs {
+        for (id, b) in filtered.benchs {
             let event = TestEvent::TeWait(b.desc.clone());
             notify_about_test_event(event)?;
             run_test(opts, false, id, b, run_strategy, tx.clone(), Concurrent::No);
@@ -432,7 +467,9 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
     }
 
     // Skip tests that match any of the skip filters
-    filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
+    if !opts.skip.is_empty() {
+        filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf)));
+    }
 
     // Excludes #[should_panic] tests
     if opts.exclude_should_panic {
diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml
index 45405a11765..dfa68578500 100644
--- a/src/doc/rustdoc/book.toml
+++ b/src/doc/rustdoc/book.toml
@@ -6,5 +6,9 @@ title = "The rustdoc book"
 git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc"
 
 [output.html.redirect]
+"/what-to-include.html" = "write-documentation/what-to-include.html"
 "/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html"
+"/linking-to-items-by-name.html" = "write-documentation/linking-to-items-by-name.html"
 "/documentation-tests.html" = "write-documentation/documentation-tests.html"
+"/website-features.html" = "advanced-features.html#custom-search-engines"
+"/passes.html" = "deprecated-features.html#passes"
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 330bdb45465..118c6779cb1 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -869,7 +869,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 
 .search-results {
 	display: none;
-	padding-bottom: 2em;
 }
 
 .search-results.active {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 8aa0abd369c..0bd0dbbeb70 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1893,7 +1893,7 @@ fn disambiguator_error(
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
         let msg = format!(
-            "see {}/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
+            "see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
             crate::DOC_RUST_LANG_ORG_CHANNEL
         );
         diag.note(&msg);
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
index e7b4c43e790..19e541736bd 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -4,7 +4,7 @@ error: unknown disambiguator `foo`
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                 ^^^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 note: the lint level is defined here
   --> $DIR/unknown-disambiguator.rs:2:9
    |
@@ -18,7 +18,7 @@ error: unknown disambiguator `bar`
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                                   ^^^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
   --> $DIR/unknown-disambiguator.rs:10:34
@@ -26,7 +26,7 @@ error: unknown disambiguator `foo`
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                  ^^^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
   --> $DIR/unknown-disambiguator.rs:10:48
@@ -34,7 +34,7 @@ error: unknown disambiguator `foo`
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                                ^^^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
   --> $DIR/unknown-disambiguator.rs:7:31
@@ -42,7 +42,7 @@ error: unknown disambiguator ``
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                               ^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
   --> $DIR/unknown-disambiguator.rs:7:57
@@ -50,7 +50,7 @@ error: unknown disambiguator ``
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                                                         ^
    |
-   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
new file mode 100644
index 00000000000..0db8088f7ee
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
@@ -0,0 +1,6 @@
+fn f() -> impl Fn() -> impl Sized { || () }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
+//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
new file mode 100644
index 00000000000..c485bc5c3ab
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
@@ -0,0 +1,15 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+  --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24
+   |
+LL | fn f() -> impl Fn() -> impl Sized { || () }
+   |                        ^^^^^^^^^^
+
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+  --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
+   |
+LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
+   |                                ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs
new file mode 100644
index 00000000000..b0aeded0ef7
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.rs
@@ -0,0 +1,8 @@
+#![feature(impl_trait_in_fn_trait_return)]
+use std::fmt::Debug;
+
+fn a() -> impl Fn(&u8) -> impl Debug {
+    |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
new file mode 100644
index 00000000000..433b76b7afa
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
@@ -0,0 +1,11 @@
+error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
+  --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
+   |
+LL |     |x| x
+   |     --- ^
+   |     |
+   |     hidden type `&u8` captures the anonymous lifetime #1 defined here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs
new file mode 100644
index 00000000000..527a4586fd7
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.rs
@@ -0,0 +1,24 @@
+#![feature(impl_trait_in_fn_trait_return)]
+use std::fmt::Debug;
+
+fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    |x| x
+}
+
+fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    |x| x
+}
+
+fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    |x| x
+}
+
+fn d() -> impl Fn() -> (impl Debug + '_) {
+    //~^ ERROR missing lifetime specifier
+    || ()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr
new file mode 100644
index 00000000000..443ffeb55cd
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-hrtb-bounds.stderr
@@ -0,0 +1,51 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/impl-fn-hrtb-bounds.rs:19:38
+   |
+LL | fn d() -> impl Fn() -> (impl Debug + '_) {
+   |                                      ^^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL | fn d() -> impl Fn() -> (impl Debug + 'static) {
+   |                                      ~~~~~~~
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/impl-fn-hrtb-bounds.rs:4:41
+   |
+LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
+   |                                         ^^
+   |
+note: lifetime declared here
+  --> $DIR/impl-fn-hrtb-bounds.rs:4:19
+   |
+LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
+   |                   ^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/impl-fn-hrtb-bounds.rs:9:52
+   |
+LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
+   |                                                    ^^
+   |
+note: lifetime declared here
+  --> $DIR/impl-fn-hrtb-bounds.rs:9:20
+   |
+LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
+   |                    ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/impl-fn-hrtb-bounds.rs:14:52
+   |
+LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
+   |                                                    ^^
+   |
+note: lifetime declared here
+  --> $DIR/impl-fn-hrtb-bounds.rs:14:20
+   |
+LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
+   |                    ^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs
new file mode 100644
index 00000000000..3e760710797
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.rs
@@ -0,0 +1,15 @@
+#![feature(impl_trait_in_fn_trait_return)]
+use std::fmt::Debug;
+
+fn a() -> impl Fn(&u8) -> impl Debug + '_ {
+    //~^ ERROR ambiguous `+` in a type
+    //~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    |x| x
+}
+
+fn b() -> impl Fn() -> impl Debug + Send {
+    //~^ ERROR ambiguous `+` in a type
+    || ()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
new file mode 100644
index 00000000000..cf6e5ef7bac
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
@@ -0,0 +1,26 @@
+error: ambiguous `+` in a type
+  --> $DIR/impl-fn-parsing-ambiguities.rs:4:27
+   |
+LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
+   |                           ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)`
+
+error: ambiguous `+` in a type
+  --> $DIR/impl-fn-parsing-ambiguities.rs:10:24
+   |
+LL | fn b() -> impl Fn() -> impl Debug + Send {
+   |                        ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)`
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/impl-fn-parsing-ambiguities.rs:4:40
+   |
+LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
+   |                                        ^^
+   |
+note: lifetime declared here
+  --> $DIR/impl-fn-parsing-ambiguities.rs:4:19
+   |
+LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
+   |                   ^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs
new file mode 100644
index 00000000000..15778662375
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.rs
@@ -0,0 +1,15 @@
+#![feature(impl_trait_in_fn_trait_return)]
+use std::fmt::Debug;
+
+fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
+    //~^ ERROR cannot resolve opaque type
+
+    |x| x
+    //~^ ERROR concrete type differs from previous defining opaque type use
+}
+
+fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {
+    a()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
new file mode 100644
index 00000000000..7747319c153
--- /dev/null
+++ b/src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
@@ -0,0 +1,24 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/impl-fn-predefined-lifetimes.rs:7:9
+   |
+LL |     |x| x
+   |         ^ expected `impl Debug + '_`, got `&u8`
+   |
+note: previous use here
+  --> $DIR/impl-fn-predefined-lifetimes.rs:7:5
+   |
+LL |     |x| x
+   |     ^^^^^
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/impl-fn-predefined-lifetimes.rs:4:35
+   |
+LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
+   |                                   ^^^^^^^^^^^^^^^ recursive opaque type
+...
+LL |     |x| x
+   |     ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/impl_fn_associativity.rs b/src/test/ui/impl-trait/impl_fn_associativity.rs
new file mode 100644
index 00000000000..71a8f9c7796
--- /dev/null
+++ b/src/test/ui/impl-trait/impl_fn_associativity.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![feature(impl_trait_in_fn_trait_return)]
+use std::fmt::Debug;
+
+fn f_debug() -> impl Fn() -> impl Debug {
+    || ()
+}
+
+fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug {
+    || f_debug()
+}
+
+fn multi() -> impl Fn() -> (impl Debug + Send) {
+    || ()
+}
+
+fn main() {
+    // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug`
+    let debug = ff_debug()()();
+    assert_eq!(format!("{:?}", debug), "()");
+
+    let x = multi()();
+    assert_eq!(format!("{:?}", x), "()");
+    fn assert_send(_: &impl Send) {}
+    assert_send(&x);
+}
diff --git a/src/test/ui/impl-trait/nested_impl_trait.rs b/src/test/ui/impl-trait/nested_impl_trait.rs
index 85c6f8c462c..e95fab3b650 100644
--- a/src/test/ui/impl-trait/nested_impl_trait.rs
+++ b/src/test/ui/impl-trait/nested_impl_trait.rs
@@ -1,3 +1,4 @@
+#![feature(impl_trait_in_fn_trait_return)]
 use std::fmt::Debug;
 
 fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
@@ -25,8 +26,7 @@ fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
 }
 
 fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
-//~^ `impl Trait` only allowed in function and inherent method return types
-    || 5
+    || 5u8
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
index 3291cad6882..9a8f5a34068 100644
--- a/src/test/ui/impl-trait/nested_impl_trait.stderr
+++ b/src/test/ui/impl-trait/nested_impl_trait.stderr
@@ -1,5 +1,5 @@
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:5:56
+  --> $DIR/nested_impl_trait.rs:6:56
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              ----------^^^^^^^^^^-
@@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:9:42
+  --> $DIR/nested_impl_trait.rs:10:42
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ----------^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:13:37
+  --> $DIR/nested_impl_trait.rs:14:37
    |
 LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           ----------^^^^^^^^^^-
@@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
    |                           outer `impl Trait`
 
 error[E0666]: nested `impl Trait` is not allowed
-  --> $DIR/nested_impl_trait.rs:18:44
+  --> $DIR/nested_impl_trait.rs:19:44
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  ----------^^^^^^^^^^-
@@ -35,19 +35,13 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  outer `impl Trait`
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
-  --> $DIR/nested_impl_trait.rs:9:32
+  --> $DIR/nested_impl_trait.rs:10:32
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |                                ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/nested_impl_trait.rs:27:42
-   |
-LL | fn allowed_in_ret_type() -> impl Fn() -> impl Into<u32> {
-   |                                          ^^^^^^^^^^^^^^
-
 error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
-  --> $DIR/nested_impl_trait.rs:5:46
+  --> $DIR/nested_impl_trait.rs:6:46
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
@@ -56,7 +50,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
 
 error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
-  --> $DIR/nested_impl_trait.rs:18:34
+  --> $DIR/nested_impl_trait.rs:19:34
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
@@ -64,7 +58,7 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0277, E0562, E0666.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs
index c1dd46c7ff7..ff63b04c268 100644
--- a/src/test/ui/impl-trait/where-allowed.rs
+++ b/src/test/ui/impl-trait/where-allowed.rs
@@ -1,5 +1,6 @@
 //! A simple test for testing many permutations of allowedness of
 //! impl Trait
+#![feature(impl_trait_in_fn_trait_return)]
 use std::fmt::Debug;
 
 // Allowed
@@ -39,9 +40,8 @@ fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
 fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
 //~^ ERROR `impl Trait` only allowed in function and inherent method return types
 
-// Disallowed
+// Allowed
 fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
 
 // Disallowed
 fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
@@ -57,9 +57,8 @@ fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
 //~^ ERROR `impl Trait` only allowed in function and inherent method return types
 //~| ERROR nested `impl Trait` is not allowed
 
-// Disallowed
+// Allowed
 fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
 
 // Disallowed
 fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
index 2e7c7ca40dd..3ad0a9f9d5c 100644
--- a/src/test/ui/impl-trait/where-allowed.stderr
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic
    |                                                 outer `impl Trait`
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/where-allowed.rs:119:16
+  --> $DIR/where-allowed.rs:118:16
    |
 LL |     type Out = impl Debug;
    |                ^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     type Out = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/where-allowed.rs:154:23
+  --> $DIR/where-allowed.rs:153:23
    |
 LL | type InTypeAlias<R> = impl Debug;
    |                       ^^^^^^^^^^
@@ -35,7 +35,7 @@ LL | type InTypeAlias<R> = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/where-allowed.rs:157:39
+  --> $DIR/where-allowed.rs:156:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
@@ -44,53 +44,47 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
-  --> $DIR/where-allowed.rs:15:40
+  --> $DIR/where-allowed.rs:16:40
    |
 LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
-  --> $DIR/where-allowed.rs:19:42
+  --> $DIR/where-allowed.rs:20:42
    |
 LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
    |                                          ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
-  --> $DIR/where-allowed.rs:23:38
+  --> $DIR/where-allowed.rs:24:38
    |
 LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
    |                                      ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
-  --> $DIR/where-allowed.rs:27:40
+  --> $DIR/where-allowed.rs:28:40
    |
 LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
-  --> $DIR/where-allowed.rs:31:49
+  --> $DIR/where-allowed.rs:32:49
    |
 LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
    |                                                 ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/where-allowed.rs:35:51
+  --> $DIR/where-allowed.rs:36:51
    |
 LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
    |                                                   ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
-  --> $DIR/where-allowed.rs:39:55
+  --> $DIR/where-allowed.rs:40:55
    |
 LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
    |                                                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/where-allowed.rs:43:57
-   |
-LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
-   |                                                         ^^^^^^^^^^
-
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
   --> $DIR/where-allowed.rs:47:51
    |
@@ -109,56 +103,50 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
 LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
    |                                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/where-allowed.rs:61:59
-   |
-LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
-   |                                                           ^^^^^^^^^^
-
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
-  --> $DIR/where-allowed.rs:65:38
+  --> $DIR/where-allowed.rs:64:38
    |
 LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
    |                                      ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/where-allowed.rs:69:40
+  --> $DIR/where-allowed.rs:68:40
    |
 LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:82:32
+  --> $DIR/where-allowed.rs:81:32
    |
 LL | struct InBraceStructField { x: impl Debug }
    |                                ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path
-  --> $DIR/where-allowed.rs:86:41
+  --> $DIR/where-allowed.rs:85:41
    |
 LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
    |                                         ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:90:27
+  --> $DIR/where-allowed.rs:89:27
    |
 LL | struct InTupleStructField(impl Debug);
    |                           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:95:25
+  --> $DIR/where-allowed.rs:94:25
    |
 LL |     InBraceVariant { x: impl Debug },
    |                         ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:97:20
+  --> $DIR/where-allowed.rs:96:20
    |
 LL |     InTupleVariant(impl Debug),
    |                    ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
-  --> $DIR/where-allowed.rs:108:23
+  --> $DIR/where-allowed.rs:107:23
    |
 LL |     fn in_return() -> impl Debug;
    |                       ^^^^^^^^^^
@@ -167,7 +155,7 @@ LL |     fn in_return() -> impl Debug;
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
-  --> $DIR/where-allowed.rs:125:34
+  --> $DIR/where-allowed.rs:124:34
    |
 LL |     fn in_trait_impl_return() -> impl Debug { () }
    |                                  ^^^^^^^^^^
@@ -176,127 +164,127 @@ LL |     fn in_trait_impl_return() -> impl Debug { () }
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param
-  --> $DIR/where-allowed.rs:138:33
+  --> $DIR/where-allowed.rs:137:33
    |
 LL |     fn in_foreign_parameters(_: impl Debug);
    |                                 ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return
-  --> $DIR/where-allowed.rs:141:31
+  --> $DIR/where-allowed.rs:140:31
    |
 LL |     fn in_foreign_return() -> impl Debug;
    |                               ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
-  --> $DIR/where-allowed.rs:157:39
+  --> $DIR/where-allowed.rs:156:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait
-  --> $DIR/where-allowed.rs:162:16
+  --> $DIR/where-allowed.rs:161:16
    |
 LL | impl PartialEq<impl Debug> for () {
    |                ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:167:24
+  --> $DIR/where-allowed.rs:166:24
    |
 LL | impl PartialEq<()> for impl Debug {
    |                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:172:6
+  --> $DIR/where-allowed.rs:171:6
    |
 LL | impl impl Debug {
    |      ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:178:24
+  --> $DIR/where-allowed.rs:177:24
    |
 LL | impl InInherentImplAdt<impl Debug> {
    |                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:184:11
+  --> $DIR/where-allowed.rs:183:11
    |
 LL |     where impl Debug: Debug
    |           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:191:15
+  --> $DIR/where-allowed.rs:190:15
    |
 LL |     where Vec<impl Debug>: Debug
    |               ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound
-  --> $DIR/where-allowed.rs:198:24
+  --> $DIR/where-allowed.rs:197:24
    |
 LL |     where T: PartialEq<impl Debug>
    |                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
-  --> $DIR/where-allowed.rs:205:17
+  --> $DIR/where-allowed.rs:204:17
    |
 LL |     where T: Fn(impl Debug)
    |                 ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
-  --> $DIR/where-allowed.rs:212:22
+  --> $DIR/where-allowed.rs:211:22
    |
 LL |     where T: Fn() -> impl Debug
    |                      ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:218:40
+  --> $DIR/where-allowed.rs:217:40
    |
 LL | struct InStructGenericParamDefault<T = impl Debug>(T);
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:222:36
+  --> $DIR/where-allowed.rs:221:36
    |
 LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
    |                                    ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:226:38
+  --> $DIR/where-allowed.rs:225:38
    |
 LL | trait InTraitGenericParamDefault<T = impl Debug> {}
    |                                      ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:230:41
+  --> $DIR/where-allowed.rs:229:41
    |
 LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
    |                                         ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:234:11
+  --> $DIR/where-allowed.rs:233:11
    |
 LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
-  --> $DIR/where-allowed.rs:241:40
+  --> $DIR/where-allowed.rs:240:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
-  --> $DIR/where-allowed.rs:247:29
+  --> $DIR/where-allowed.rs:246:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return
-  --> $DIR/where-allowed.rs:249:46
+  --> $DIR/where-allowed.rs:248:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:234:7
+  --> $DIR/where-allowed.rs:233:7
    |
 LL | impl <T = impl Debug> T {}
    |       ^^^^^^^^^^^^^^
@@ -306,7 +294,7 @@ LL | impl <T = impl Debug> T {}
    = note: `#[deny(invalid_type_param_default)]` on by default
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:241:36
+  --> $DIR/where-allowed.rs:240:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^^^^^^^^^^^^^^
@@ -315,14 +303,14 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
 
 error[E0118]: no nominal type found for inherent implementation
-  --> $DIR/where-allowed.rs:234:23
+  --> $DIR/where-allowed.rs:233:23
    |
 LL | impl <T = impl Debug> T {}
    |                       ^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
-error: aborting due to 49 previous errors
+error: aborting due to 47 previous errors
 
 Some errors have detailed explanations: E0118, E0562, E0658, E0666.
 For more information about an error, try `rustc --explain E0118`.
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index 53598545223..f0eaa1a5c64 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -2,7 +2,7 @@ error[E0574]: expected struct, variant or union type, found type parameter `T`
   --> $DIR/lexical-scopes.rs:3:13
    |
 LL | struct T { i: i32 }
-   | ------------------- you might have meant to refer to this struct
+   |        - you might have meant to refer to this struct
 LL | fn f<T>() {
    |      - found this type parameter
 LL |     let t = T { i: 0 };
diff --git a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
index eb26cd9cabb..5790e425c0a 100644
--- a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
+++ b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
@@ -1,16 +1,14 @@
 error[E0574]: expected struct, variant or union type, found type parameter `Baz`
   --> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
    |
-LL | / struct Baz {
-LL | |     num: usize,
-LL | | }
-   | |_- you might have meant to refer to this struct
-LL |
-LL |   impl<Baz> Foo<Baz> for Bar {
-   |        --- found this type parameter
+LL | struct Baz {
+   |        --- you might have meant to refer to this struct
 ...
-LL |               Baz { num } => num,
-   |               ^^^ not a struct, variant or union type
+LL | impl<Baz> Foo<Baz> for Bar {
+   |      --- found this type parameter
+...
+LL |             Baz { num } => num,
+   |             ^^^ not a struct, variant or union type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index d8fddc8007f..057d40ac0cb 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -1,6 +1,9 @@
 error[E0404]: expected trait, found type parameter `Add`
   --> $DIR/issue-35987.rs:5:21
    |
+LL | use std::ops::Add;
+   |               --- you might have meant to refer to this trait
+LL |
 LL | impl<T: Clone, Add> Add for Foo<T> {
    |                ---  ^^^ not a trait
    |                |