Skip to content

Commit a254fa8

Browse files
committed
Auto merge of #158498 - JonathanBrouwer:rollup-3xKakOD, r=JonathanBrouwer
Rollup of 6 pull requests Successful merges: - #158194 (Adds RmetaLinkCache a per-link cache that uses path as the key of dec…) - #137858 (Add new `unused_footnote_definition` rustdoc lint) - #158163 (Fix too-short variance slice in `variances_of` cycle recovery) - #158233 (Allow the unstable attribute on foreign type) - #158470 (Upgrade `jsonsocck` and `jsondoclint` to edition 2024.) - #158488 (Upgrade `rustdoc-json-types` to 2024 edition.)
2 parents 13f1859 + bc0899f commit a254fa8

18 files changed

Lines changed: 366 additions & 59 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/stability.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
4040
Allow(Target::Static),
4141
Allow(Target::ForeignFn),
4242
Allow(Target::ForeignStatic),
43+
Allow(Target::ForeignTy),
4344
Allow(Target::ExternCrate),
4445
]);
4546

compiler/rustc_codegen_ssa/src/back/archive.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_target::spec::Arch;
2222
use tracing::trace;
2323

2424
use super::metadata::{create_compressed_metadata_file, search_for_section};
25-
use super::rmeta_link;
25+
use super::rmeta_link::{self, RmetaLinkCache};
2626
use super::symbol_edit::{apply_edits, collect_internal_names};
2727
use crate::common;
2828
// Public for ArchiveBuilderBuilder::extract_bundled_libs
@@ -311,7 +311,7 @@ fn find_binutils_dlltool(sess: &Session) -> OsString {
311311
}
312312

313313
pub enum AddArchiveKind<'a> {
314-
Rlib(/*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool),
314+
Rlib(&'a mut RmetaLinkCache, /*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool),
315315
Other,
316316
}
317317

@@ -466,7 +466,11 @@ pub fn try_extract_macho_fat_archive(
466466
}
467467

468468
impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
469-
fn add_archive(&mut self, archive_path: &Path, ar_kind: AddArchiveKind<'_>) -> io::Result<()> {
469+
fn add_archive(
470+
&mut self,
471+
archive_path: &Path,
472+
mut ar_kind: AddArchiveKind<'_>,
473+
) -> io::Result<()> {
470474
let mut archive_path = archive_path.to_path_buf();
471475
if self.sess.target.llvm_target.contains("-apple-macosx")
472476
&& let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)?
@@ -481,8 +485,14 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
481485
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
482486
let archive = ArchiveFile::parse(&*archive_map)
483487
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
484-
let metadata_link = match ar_kind {
485-
AddArchiveKind::Rlib(..) => rmeta_link::read(&archive, &archive_map, &archive_path),
488+
let skip = match &ar_kind {
489+
AddArchiveKind::Rlib(_, skip) => Some(*skip),
490+
AddArchiveKind::Other => None,
491+
};
492+
let metadata_link = match &mut ar_kind {
493+
AddArchiveKind::Rlib(cache, _) => cache.get_or_insert_with(&archive_path, || {
494+
rmeta_link::read(&archive, &archive_map, &archive_path)
495+
}),
486496
AddArchiveKind::Other => None,
487497
};
488498
let archive_index = self.src_archives.len();
@@ -512,9 +522,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
512522
} else {
513523
ArchiveEntryKind::Other
514524
};
515-
let drop = match ar_kind {
516-
AddArchiveKind::Rlib(skip) => skip(&file_name, kind),
517-
AddArchiveKind::Other => false,
525+
let drop = match skip {
526+
Some(skip) => skip(&file_name, kind),
527+
None => false,
518528
};
519529
if !drop {
520530
let source = if entry.is_thin() {

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use super::archive::{
5959
use super::command::Command;
6060
use super::linker::{self, Linker};
6161
use super::metadata::{MetadataPosition, create_wrapper_file};
62+
use super::rmeta_link::RmetaLinkCache;
6263
use super::rpath::{self, RPathConfig};
6364
use super::{apple, rmeta_link, versioned_llvm_target};
6465
use crate::base::needs_allocator_shim_for_linking;
@@ -86,6 +87,7 @@ pub fn link_binary(
8687
let _timer = sess.timer("link_binary");
8788
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
8889
let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
90+
let mut rmeta_link_cache = RmetaLinkCache::default();
8991
for &crate_type in &crate_info.crate_types {
9092
// Ignore executable crates if we have -Z no-codegen, as they will error.
9193
if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
@@ -139,6 +141,7 @@ pub fn link_binary(
139141
link_staticlib(
140142
sess,
141143
archive_builder_builder,
144+
&mut rmeta_link_cache,
142145
&compiled_modules,
143146
&crate_info,
144147
&metadata,
@@ -150,6 +153,7 @@ pub fn link_binary(
150153
link_natively(
151154
sess,
152155
archive_builder_builder,
156+
&mut rmeta_link_cache,
153157
crate_type,
154158
&out_filename,
155159
&compiled_modules,
@@ -502,6 +506,7 @@ fn link_rlib<'a>(
502506
fn link_staticlib(
503507
sess: &Session,
504508
archive_builder_builder: &dyn ArchiveBuilderBuilder,
509+
rmeta_link_cache: &mut RmetaLinkCache,
505510
compiled_modules: &CompiledModules,
506511
crate_info: &CrateInfo,
507512
metadata: &EncodedMetadata,
@@ -531,7 +536,7 @@ fn link_staticlib(
531536
let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
532537
ab.add_archive(
533538
path,
534-
AddArchiveKind::Rlib(&|fname: &str, entry_kind| {
539+
AddArchiveKind::Rlib(rmeta_link_cache, &|fname: &str, entry_kind| {
535540
// Ignore metadata and rmeta-link files.
536541
if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME {
537542
return true;
@@ -939,6 +944,7 @@ fn report_linker_output(
939944
fn link_natively(
940945
sess: &Session,
941946
archive_builder_builder: &dyn ArchiveBuilderBuilder,
947+
rmeta_link_cache: &mut RmetaLinkCache,
942948
crate_type: CrateType,
943949
out_filename: &Path,
944950
compiled_modules: &CompiledModules,
@@ -965,6 +971,7 @@ fn link_natively(
965971
flavor,
966972
sess,
967973
archive_builder_builder,
974+
rmeta_link_cache,
968975
crate_type,
969976
tmpdir,
970977
temp_filename,
@@ -2562,6 +2569,7 @@ fn linker_with_args(
25622569
flavor: LinkerFlavor,
25632570
sess: &Session,
25642571
archive_builder_builder: &dyn ArchiveBuilderBuilder,
2572+
rmeta_link_cache: &mut RmetaLinkCache,
25652573
crate_type: CrateType,
25662574
tmpdir: &Path,
25672575
out_filename: &Path,
@@ -2690,6 +2698,7 @@ fn linker_with_args(
26902698
cmd,
26912699
sess,
26922700
archive_builder_builder,
2701+
rmeta_link_cache,
26932702
crate_info,
26942703
crate_type,
26952704
tmpdir,
@@ -3126,6 +3135,7 @@ fn add_upstream_rust_crates(
31263135
cmd: &mut dyn Linker,
31273136
sess: &Session,
31283137
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3138+
rmeta_link_cache: &mut RmetaLinkCache,
31293139
crate_info: &CrateInfo,
31303140
crate_type: CrateType,
31313141
tmpdir: &Path,
@@ -3178,6 +3188,7 @@ fn add_upstream_rust_crates(
31783188
cmd,
31793189
sess,
31803190
archive_builder_builder,
3191+
rmeta_link_cache,
31813192
crate_info,
31823193
tmpdir,
31833194
cnum,
@@ -3309,6 +3320,7 @@ fn add_static_crate(
33093320
cmd: &mut dyn Linker,
33103321
sess: &Session,
33113322
archive_builder_builder: &dyn ArchiveBuilderBuilder,
3323+
rmeta_link_cache: &mut RmetaLinkCache,
33123324
crate_info: &CrateInfo,
33133325
tmpdir: &Path,
33143326
cnum: CrateNum,
@@ -3339,7 +3351,7 @@ fn add_static_crate(
33393351
let mut archive = archive_builder_builder.new_archive_builder(sess);
33403352
if let Err(error) = archive.add_archive(
33413353
cratepath,
3342-
AddArchiveKind::Rlib(&|f, entry_kind| {
3354+
AddArchiveKind::Rlib(rmeta_link_cache, &|f, entry_kind| {
33433355
if f == METADATA_FILENAME || f == rmeta_link::FILENAME {
33443356
return true;
33453357
}

compiler/rustc_codegen_ssa/src/back/rmeta_link.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
//! and potentially other data collected and used when building or linking a rlib.
33
//! See <https://github.com/rust-lang/rust/issues/138243>.
44
5-
use std::path::Path;
5+
use std::path::{Path, PathBuf};
66

77
use object::read::archive::ArchiveFile;
8+
use rustc_data_structures::fx::FxHashMap;
89
use rustc_serialize::opaque::mem_encoder::MemEncoder;
910
use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder};
1011
use rustc_serialize::{Decodable, Encodable};
@@ -54,3 +55,18 @@ pub fn read_from_data(archive_data: &[u8], rlib_path: &Path) -> Option<RmetaLink
5455
let archive = ArchiveFile::parse(archive_data).ok()?;
5556
read(&archive, archive_data, rlib_path)
5657
}
58+
59+
#[derive(Default)]
60+
pub struct RmetaLinkCache {
61+
cache: FxHashMap<PathBuf, Option<RmetaLink>>,
62+
}
63+
64+
impl RmetaLinkCache {
65+
pub fn get_or_insert_with(
66+
&mut self,
67+
rlib_path: &Path,
68+
load: impl FnOnce() -> Option<RmetaLink>,
69+
) -> Option<&RmetaLink> {
70+
self.cache.entry(rlib_path.to_path_buf()).or_insert_with(load).as_ref()
71+
}
72+
}

compiler/rustc_query_impl/src/handle_cycle_error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub(crate) fn variances_of<'tcx>(
105105
err: Diag<'_>,
106106
) -> &'tcx [ty::Variance] {
107107
let _guar = err.delay_as_bug();
108-
let n = tcx.generics_of(def_id).own_params.len();
108+
let n = tcx.generics_of(def_id).count();
109109
tcx.arena.alloc_from_iter(iter::repeat_n(ty::Bivariant, n))
110110
}
111111

src/librustdoc/lint.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,20 @@ declare_rustdoc_lint! {
196196
"detects redundant explicit links in doc comments"
197197
}
198198

199+
declare_rustdoc_lint! {
200+
/// This lint checks for uses of footnote references without definition.
201+
BROKEN_FOOTNOTE,
202+
Warn,
203+
"detects footnote references with no associated definition"
204+
}
205+
206+
declare_rustdoc_lint! {
207+
/// This lint checks if all footnote definitions are used.
208+
UNUSED_FOOTNOTE_DEFINITION,
209+
Warn,
210+
"detects unused footnote definitions"
211+
}
212+
199213
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
200214
vec![
201215
BROKEN_INTRA_DOC_LINKS,
@@ -209,6 +223,8 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
209223
MISSING_CRATE_LEVEL_DOCS,
210224
UNESCAPED_BACKTICKS,
211225
REDUNDANT_EXPLICIT_LINKS,
226+
BROKEN_FOOTNOTE,
227+
UNUSED_FOOTNOTE_DEFINITION,
212228
]
213229
});
214230

src/librustdoc/passes/lint.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
mod bare_urls;
55
mod check_code_block_syntax;
6+
mod footnotes;
67
mod html_tags;
78
mod redundant_explicit_links;
89
mod unescaped_backticks;
@@ -41,6 +42,7 @@ impl DocVisitor<'_> for Linter<'_, '_> {
4142
if may_have_link {
4243
bare_urls::visit_item(self.cx, item, hir_id, &dox);
4344
redundant_explicit_links::visit_item(self.cx, item, hir_id);
45+
footnotes::visit_item(self.cx, item, hir_id, &dox);
4446
}
4547
if may_have_code {
4648
check_code_block_syntax::visit_item(self.cx, item, &dox);
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use std::ops::Range;
2+
3+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4+
use rustc_errors::DiagDecorator;
5+
use rustc_hir::HirId;
6+
use rustc_lint_defs::Applicability;
7+
use rustc_resolve::rustdoc::pulldown_cmark::{Event, Options, Parser, Tag};
8+
use rustc_resolve::rustdoc::source_span_for_markdown_range;
9+
10+
use crate::clean::Item;
11+
use crate::core::DocContext;
12+
13+
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) {
14+
let tcx = cx.tcx;
15+
16+
let mut missing_footnote_references = FxHashSet::default();
17+
let mut footnote_references = FxHashSet::default();
18+
let mut footnote_definitions = FxHashMap::default();
19+
20+
let options = Options::ENABLE_FOOTNOTES;
21+
let mut parser = Parser::new_ext(dox, options).into_offset_iter().peekable();
22+
while let Some((event, span)) = parser.next() {
23+
match event {
24+
Event::Text(text)
25+
if &*text == "["
26+
&& (span.start == 0 || dox.as_bytes().get(span.start - 1) != Some(&b'\\'))
27+
&& let Some(len) = scan_footnote_ref(&dox[span.start..]) =>
28+
{
29+
missing_footnote_references
30+
.insert(Range { start: span.start, end: span.start + len });
31+
}
32+
Event::FootnoteReference(label) => {
33+
footnote_references.insert(label);
34+
}
35+
Event::Start(Tag::FootnoteDefinition(label)) => {
36+
footnote_definitions.insert(label, span.start + 1);
37+
}
38+
_ => {}
39+
}
40+
}
41+
42+
#[allow(rustc::potential_query_instability)]
43+
for (footnote, span) in footnote_definitions {
44+
if !footnote_references.contains(&footnote) {
45+
let (span, _) = source_span_for_markdown_range(
46+
tcx,
47+
dox,
48+
&(span..span + 1),
49+
&item.attrs.doc_strings,
50+
)
51+
.unwrap_or_else(|| (item.attr_span(tcx), false));
52+
53+
tcx.emit_node_span_lint(
54+
crate::lint::UNUSED_FOOTNOTE_DEFINITION,
55+
hir_id,
56+
span,
57+
DiagDecorator(|lint| {
58+
lint.primary_message("unused footnote definition");
59+
}),
60+
);
61+
}
62+
}
63+
64+
#[allow(rustc::potential_query_instability)]
65+
for span in missing_footnote_references {
66+
let ref_span = source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings)
67+
.map(|(span, _)| span)
68+
.unwrap_or_else(|| item.attr_span(tcx));
69+
70+
tcx.emit_node_span_lint(
71+
crate::lint::BROKEN_FOOTNOTE,
72+
hir_id,
73+
ref_span,
74+
DiagDecorator(|lint| {
75+
lint.primary_message("no footnote definition matching this footnote");
76+
lint.span_suggestion(
77+
ref_span.shrink_to_lo(),
78+
"if it should not be a footnote, escape it",
79+
"\\",
80+
Applicability::MaybeIncorrect,
81+
);
82+
}),
83+
);
84+
}
85+
}
86+
87+
fn scan_footnote_ref(dox: &str) -> Option<usize> {
88+
let dox = dox.as_bytes();
89+
let mut i = 0;
90+
if dox.get(i) != Some(&b'[') {
91+
return None;
92+
}
93+
i += 1;
94+
if dox.get(i) != Some(&b'^') {
95+
return None;
96+
}
97+
i += 1;
98+
while let Some(&c) = dox.get(i) {
99+
if c == b']' {
100+
i += 1;
101+
return Some(i);
102+
}
103+
if c == b'\r' || c == b'\n' || c == b'[' {
104+
// Can't nest things like this.
105+
break;
106+
}
107+
if c == b'\\' {
108+
i += 1;
109+
}
110+
if dox.get(i) == Some(&b'\r') || dox.get(i) == Some(&b'\n') {
111+
// Can't have line breaks in footnote refs
112+
break;
113+
}
114+
i += 1;
115+
}
116+
None
117+
}

src/rustdoc-json-types/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "rustdoc-json-types"
33
version = "0.1.0"
4-
edition = "2021"
4+
edition = "2024"
55

66
[lib]
77
path = "lib.rs"

0 commit comments

Comments
 (0)