about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/types.rs9
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs29
-rw-r--r--src/librustdoc/html/markdown.rs11
-rw-r--r--src/librustdoc/html/render/mod.rs29
-rw-r--r--src/librustdoc/html/render/print_item.rs13
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs15
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/passes/lint/bare_urls.rs5
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs4
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs5
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs10
-rw-r--r--src/librustdoc/passes/lint/unescaped_backticks.rs73
-rw-r--r--src/librustdoc/scrape_examples.rs6
17 files changed, 153 insertions, 69 deletions
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b54ec624524..7490688e36c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -627,7 +627,7 @@ impl Item {
         ) -> hir::FnHeader {
             let sig = tcx.fn_sig(def_id).skip_binder();
             let constness =
-                if tcx.is_const_fn(def_id) && is_unstable_const_fn(tcx, def_id).is_none() {
+                if tcx.is_const_fn(def_id) || is_unstable_const_fn(tcx, def_id).is_some() {
                     hir::Constness::Const
                 } else {
                     hir::Constness::NotConst
@@ -649,9 +649,8 @@ impl Item {
                         hir::Safety::Unsafe
                     },
                     abi,
-                    constness: if abi == Abi::RustIntrinsic
-                        && tcx.is_const_fn(def_id)
-                        && is_unstable_const_fn(tcx, def_id).is_none()
+                    constness: if tcx.is_const_fn(def_id)
+                        || is_unstable_const_fn(tcx, def_id).is_some()
                     {
                         hir::Constness::Const
                     } else {
@@ -1937,7 +1936,7 @@ impl PrimitiveType {
             let mut primitive_locations = FxHashMap::default();
             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
             // This is a degenerate case that I don't plan to support.
-            for &crate_num in tcx.crates(()) {
+            for &crate_num in tcx.crates_including_speculative(()) {
                 let e = ExternalCrate { crate_num };
                 let crate_name = e.name(tcx);
                 debug!(?crate_num, ?crate_name);
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index feb03b9a823..93229527076 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt(
         show_coverage,
     };
 
-    for cnum in tcx.crates(()) {
+    for cnum in tcx.crates_including_speculative(()) {
         crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id());
     }
 
@@ -372,8 +372,8 @@ pub(crate) fn run_global_ctxt(
         tcx.node_lint(
             crate::lint::MISSING_CRATE_LEVEL_DOCS,
             DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
-            "no documentation found for this crate's top-level module",
             |lint| {
+                lint.primary_message("no documentation found for this crate's top-level module");
                 lint.help(help);
             },
         );
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index a3b88a880f2..28ddf76a3a6 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -155,7 +155,7 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &crate_num in tcx.crates(()) {
+        for &crate_num in tcx.crates_including_speculative(()) {
             let e = ExternalCrate { crate_num };
 
             let name = e.name(tcx);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 587c464b0ed..57949001774 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -13,7 +13,7 @@ use std::fmt::{self, Display, Write};
 use std::iter::{self, once};
 
 use rustc_ast as ast;
-use rustc_attr::{ConstStability, StabilityLevel};
+use rustc_attr::{ConstStability, StabilityLevel, StableSince};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -1633,17 +1633,24 @@ impl PrintWithSpace for hir::Mutability {
 
 pub(crate) fn print_constness_with_space(
     c: &hir::Constness,
-    s: Option<ConstStability>,
+    overall_stab: Option<StableSince>,
+    const_stab: Option<ConstStability>,
 ) -> &'static str {
-    match (c, s) {
-        // const stable or when feature(staged_api) is not set
-        (
-            hir::Constness::Const,
-            Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }),
-        )
-        | (hir::Constness::Const, None) => "const ",
-        // const unstable or not const
-        _ => "",
+    match c {
+        hir::Constness::Const => match (overall_stab, const_stab) {
+            // const stable...
+            (_, Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }))
+            // ...or when feature(staged_api) is not set...
+            | (_, None)
+            // ...or when const unstable, but overall unstable too
+            | (None, Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => {
+                "const "
+            }
+            // const unstable (and overall stable)
+            (Some(_), Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. })) => "",
+        },
+        // not const
+        hir::Constness::NotConst => "",
     }
 }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5c5651f3ef0..362f9021671 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -834,8 +834,9 @@ impl<'tcx> ExtraInfo<'tcx> {
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
                 self.tcx.local_def_id_to_hir_id(def_id),
                 self.sp,
-                msg,
-                |_| {},
+                |lint| {
+                    lint.primary_message(msg);
+                },
             );
         }
     }
@@ -850,8 +851,10 @@ impl<'tcx> ExtraInfo<'tcx> {
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
                 self.tcx.local_def_id_to_hir_id(def_id),
                 self.sp,
-                msg,
-                f,
+                |lint| {
+                    lint.primary_message(msg);
+                    f(lint);
+                },
             );
         }
     }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index f3ae4b76883..8ee4cc5c75e 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -928,9 +928,11 @@ fn assoc_method(
     // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
     // this condition.
     let constness = match render_mode {
-        RenderMode::Normal => {
-            print_constness_with_space(&header.constness, meth.const_stability(tcx))
-        }
+        RenderMode::Normal => print_constness_with_space(
+            &header.constness,
+            meth.stable_since(tcx),
+            meth.const_stability(tcx),
+        ),
         RenderMode::ForDeref { .. } => "",
     };
     let asyncness = header.asyncness.print_with_space();
@@ -1016,18 +1018,23 @@ fn render_stability_since_raw_with_extra(
                 .map(|since| (format!("const since {since}"), format!("const: {since}")))
         }
         Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }) => {
-            let unstable = if let Some(n) = issue {
-                format!(
-                    "<a \
+            if stable_version.is_none() {
+                // don't display const unstable if entirely unstable
+                None
+            } else {
+                let unstable = if let Some(n) = issue {
+                    format!(
+                        "<a \
                         href=\"https://github.com/rust-lang/rust/issues/{n}\" \
                         title=\"Tracking issue for {feature}\"\
                        >unstable</a>"
-                )
-            } else {
-                String::from("unstable")
-            };
+                    )
+                } else {
+                    String::from("unstable")
+                };
 
-            Some((String::from("const unstable"), format!("const: {unstable}")))
+                Some((String::from("const unstable"), format!("const: {unstable}")))
+            }
         }
         _ => None,
     };
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index c7a23aa8503..c5b88c7a951 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -615,7 +615,18 @@ fn extra_info_tags<'a, 'tcx: 'a>(
 fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
     let tcx = cx.tcx();
     let header = it.fn_header(tcx).expect("printing a function which isn't a function");
-    let constness = print_constness_with_space(&header.constness, it.const_stability(tcx));
+    debug!(
+        "item_function/const: {:?} {:?} {:?} {:?}",
+        it.name,
+        &header.constness,
+        it.stable_since(tcx),
+        it.const_stability(tcx),
+    );
+    let constness = print_constness_with_space(
+        &header.constness,
+        it.stable_since(tcx),
+        it.const_stability(tcx),
+    );
     let safety = header.safety.print_with_space();
     let abi = print_abi_with_space(header.abi).to_string();
     let asyncness = header.asyncness.print_with_space();
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 0650afb90c7..55346c768b6 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -8,7 +8,6 @@
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
-#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(round_char_boundary)]
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index e85b998bfbe..257bab3e9fc 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -125,13 +125,9 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
         if should_have_doc_example(cx, item) {
             debug!("reporting error for {item:?} (hir_id={hir_id:?})");
             let sp = item.attr_span(cx.tcx);
-            cx.tcx.node_span_lint(
-                crate::lint::MISSING_DOC_CODE_EXAMPLES,
-                hir_id,
-                sp,
-                "missing code example in this documentation",
-                |_| {},
-            );
+            cx.tcx.node_span_lint(crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id, sp, |lint| {
+                lint.primary_message("missing code example in this documentation");
+            });
         }
     } else if tests.found_tests > 0
         && !cx.cache.effective_visibilities.is_exported(cx.tcx, item.item_id.expect_def_id())
@@ -140,8 +136,9 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
             crate::lint::PRIVATE_DOC_TESTS,
             hir_id,
             item.attr_span(cx.tcx),
-            "documentation test in private item",
-            |_| {},
+            |lint| {
+                lint.primary_message("documentation test in private item");
+            },
         );
     }
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 747f5c0a835..8ab24a8c12e 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1689,7 +1689,9 @@ fn report_diagnostic(
 
     let sp = item.attr_span(tcx);
 
-    tcx.node_span_lint(lint, hir_id, sp, msg, |lint| {
+    tcx.node_span_lint(lint, hir_id, sp, |lint| {
+        lint.primary_message(msg);
+
         let (span, link_range) = match link_range {
             MarkdownLinkRange::Destination(md_range) => {
                 let mut md_range = md_range.clone();
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index c92cf9d3e80..22daac9efb1 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
     // External trait impls.
     {
         let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls");
-        for &cnum in tcx.crates(()) {
+        for &cnum in tcx.crates_including_speculative(()) {
             for &impl_def_id in tcx.trait_impls_in_crate(cnum) {
                 cx.with_param_env(impl_def_id, |cx| {
                     inline::build_impl(cx, impl_def_id, None, &mut new_items_external);
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index c6989fbbf25..8f68f6ff476 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -24,8 +24,9 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                 let sp =
                     source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings)
                         .unwrap_or_else(|| item.attr_span(cx.tcx));
-                cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
-                    lint.note("bare URLs are not automatically turned into clickable links")
+                cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| {
+                    lint.primary_message(msg)
+                        .note("bare URLs are not automatically turned into clickable links")
                         .span_suggestion(
                             sp,
                             "use an automatic link instead",
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 7b81b5e63be..9562559fba2 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -99,7 +99,9 @@ fn check_rust_syntax(
     // All points of divergence have been handled earlier so this can be
     // done the same way whether the span is precise or not.
     let hir_id = cx.tcx.local_def_id_to_hir_id(local_id);
-    cx.tcx.node_span_lint(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, msg, |lint| {
+    cx.tcx.node_span_lint(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, |lint| {
+        lint.primary_message(msg);
+
         let explanation = if is_ignore {
             "`ignore` code blocks require valid Rust code for syntax highlighting; \
                     mark blocks that do not contain Rust code as text"
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index da3770aa927..25b0c61b826 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -25,8 +25,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                 Some(sp) => sp,
                 None => item.attr_span(tcx),
             };
-            tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
+            tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
                 use rustc_lint_defs::Applicability;
+
+                lint.primary_message(msg);
+
                 // If a tag looks like `<this>`, it might actually be a generic.
                 // We don't try to detect stuff `<like, this>` because that's not valid HTML,
                 // and we don't try to detect stuff `<like this>` because that's not valid Rust.
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 09886024595..7ab974046b9 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -188,8 +188,9 @@ fn check_inline_or_reference_unknown_redundancy(
             &item.attrs.doc_strings,
         )?;
 
-        cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
-            lint.span_label(explicit_span, "explicit target is redundant")
+        cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, |lint| {
+            lint.primary_message("redundant explicit link target")
+                .span_label(explicit_span, "explicit target is redundant")
                 .span_label(display_span, "because label contains path that resolves to same destination")
                 .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
                 .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
@@ -238,8 +239,9 @@ fn check_reference_redundancy(
             &item.attrs.doc_strings,
         )?;
 
-        cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
-            lint.span_label(explicit_span, "explicit target is redundant")
+        cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, |lint| {
+            lint.primary_message("redundant explicit link target")
+            .span_label(explicit_span, "explicit target is redundant")
                 .span_label(display_span, "because label contains path that resolves to same destination")
                 .span_note(def_span, "referenced explicit link target defined here")
                 .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
index 4ea926cb79a..be9670077d1 100644
--- a/src/librustdoc/passes/lint/unescaped_backticks.rs
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -56,17 +56,28 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                 )
                 .unwrap_or_else(|| item.attr_span(tcx));
 
-                tcx.node_span_lint(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| {
+                tcx.node_span_lint(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, |lint| {
+                    lint.primary_message("unescaped backtick");
+
                     let mut help_emitted = false;
 
                     match element.prev_code_guess {
                         PrevCodeGuess::None => {}
                         PrevCodeGuess::Start { guess, .. } => {
                             // "foo` `bar`" -> "`foo` `bar`"
-                            if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
+                            if let Some(suggest_index) =
+                                clamp_start(guess, &element.suggestible_ranges)
                                 && can_suggest_backtick(&dox, suggest_index)
                             {
-                                suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of a previous inline code may be missing");
+                                suggest_insertion(
+                                    cx,
+                                    item,
+                                    &dox,
+                                    lint,
+                                    suggest_index,
+                                    '`',
+                                    "the opening backtick of a previous inline code may be missing",
+                                );
                                 help_emitted = true;
                             }
                         }
@@ -76,7 +87,15 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                             // an inline code node and we intentionally "break" the inline code here.
                             let suggest_index = guess;
                             if can_suggest_backtick(&dox, suggest_index) {
-                                suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "a previous inline code might be longer than expected");
+                                suggest_insertion(
+                                    cx,
+                                    item,
+                                    &dox,
+                                    lint,
+                                    suggest_index,
+                                    '`',
+                                    "a previous inline code might be longer than expected",
+                                );
                                 help_emitted = true;
                             }
                         }
@@ -84,11 +103,21 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
 
                     if !element.prev_code_guess.is_confident() {
                         // "`foo` bar`" -> "`foo` `bar`"
-                        if let Some(guess) = guess_start_of_code(&dox, element.element_range.start..backtick_index)
-                            && let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
+                        if let Some(guess) =
+                            guess_start_of_code(&dox, element.element_range.start..backtick_index)
+                            && let Some(suggest_index) =
+                                clamp_start(guess, &element.suggestible_ranges)
                             && can_suggest_backtick(&dox, suggest_index)
                         {
-                            suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of an inline code may be missing");
+                            suggest_insertion(
+                                cx,
+                                item,
+                                &dox,
+                                lint,
+                                suggest_index,
+                                '`',
+                                "the opening backtick of an inline code may be missing",
+                            );
                             help_emitted = true;
                         }
 
@@ -96,21 +125,41 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                         // Don't suggest closing backtick after single trailing char,
                         // if we already suggested opening backtick. For example:
                         // "foo`." -> "`foo`." or "foo`s" -> "`foo`s".
-                        if let Some(guess) = guess_end_of_code(&dox, backtick_index + 1..element.element_range.end)
-                            && let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges)
+                        if let Some(guess) =
+                            guess_end_of_code(&dox, backtick_index + 1..element.element_range.end)
+                            && let Some(suggest_index) =
+                                clamp_end(guess, &element.suggestible_ranges)
                             && can_suggest_backtick(&dox, suggest_index)
                             && (!help_emitted || suggest_index - backtick_index > 2)
                         {
-                            suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the closing backtick of an inline code may be missing");
+                            suggest_insertion(
+                                cx,
+                                item,
+                                &dox,
+                                lint,
+                                suggest_index,
+                                '`',
+                                "the closing backtick of an inline code may be missing",
+                            );
                             help_emitted = true;
                         }
                     }
 
                     if !help_emitted {
-                        lint.help("the opening or closing backtick of an inline code may be missing");
+                        lint.help(
+                            "the opening or closing backtick of an inline code may be missing",
+                        );
                     }
 
-                    suggest_insertion(cx, item, &dox, lint, backtick_index, '\\', "if you meant to use a literal backtick, escape it");
+                    suggest_insertion(
+                        cx,
+                        item,
+                        &dox,
+                        lint,
+                        backtick_index,
+                        '\\',
+                        "if you meant to use a literal backtick, escape it",
+                    );
                 });
             }
             Event::Code(_) => {
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 9c9b386edda..64753a58a2b 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -283,7 +283,7 @@ pub(crate) fn run(
         // Collect CrateIds corresponding to provided target crates
         // If two different versions of the crate in the dependency tree, then examples will be collected from both.
         let all_crates = tcx
-            .crates(())
+            .crates_including_speculative(())
             .iter()
             .chain([&LOCAL_CRATE])
             .map(|crate_num| (crate_num, tcx.crate_name(*crate_num)))
@@ -344,7 +344,9 @@ pub(crate) fn load_call_locations(
             Ok(bytes) => bytes,
             Err(e) => dcx.fatal(format!("failed to load examples: {e}")),
         };
-        let mut decoder = MemDecoder::new(&bytes, 0);
+        let Ok(mut decoder) = MemDecoder::new(&bytes, 0) else {
+            dcx.fatal(format!("Corrupt metadata encountered in {path}"))
+        };
         let calls = AllCallLocations::decode(&mut decoder);
 
         for (function, fn_calls) in calls.into_iter() {