diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 07ffd06511885..b1dd6aef97493 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -24,7 +24,7 @@ impl char { /// decoding error. /// /// It can occur, for example, when giving ill-formed UTF-8 bytes to - /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy). + /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy). #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b67038a7d5c2c..a04e479e8570d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2257,9 +2257,9 @@ impl [T] { /// assert!(match r { Ok(1..=4) => true, _ => false, }); /// ``` // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is - // in crate `alloc`, and as such doesn't exists yet when building `core`. - // links to downstream crate: #74481. Since primitives are only documented in - // libstd (#73423), this never leads to broken links in practice. + // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481. + // This breaks links when slice is displayed in core, but changing it to use relative links + // would break when the item is re-exported. So allow the core links to be broken for now. #[allow(rustdoc::broken_intra_doc_links)] #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] #[inline] diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index be1532d450150..454602481e3c5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1774,7 +1774,7 @@ impl PrimitiveType { debug!(?crate_num, ?crate_name); for &(def_id, prim) in &e.primitives(tcx) { // HACK: try to link to std instead where possible - if crate_name == sym::core && primitive_locations.get(&prim).is_some() { + if crate_name == sym::core && primitive_locations.contains_key(&prim) { continue; } primitive_locations.insert(prim, def_id); diff --git a/src/test/rustdoc-js-std/multi-query.js b/src/test/rustdoc-js-std/multi-query.js index 01e54065189c5..1c92d019606b6 100644 --- a/src/test/rustdoc-js-std/multi-query.js +++ b/src/test/rustdoc-js-std/multi-query.js @@ -2,8 +2,9 @@ const QUERY = 'str,u8'; const EXPECTED = { 'others': [ - { 'path': 'std', 'name': 'str' }, - { 'path': 'std', 'name': 'u8' }, - { 'path': 'std::ffi', 'name': 'CStr' }, + { 'path': 'std', 'name': 'str', 'href': '../std/primitive.str.html' }, + { 'path': 'std', 'name': 'u8', 'href': '../std/primitive.u8.html' }, + { 'path': 'std', 'name': 'str', 'href': '../std/str/index.html' }, + { 'path': 'std', 'name': 'u8', 'href': '../std/u8/index.html' }, ], }; diff --git a/src/test/rustdoc/primitive/no_std.rs b/src/test/rustdoc/primitive/no_std.rs index 52806bd94f9a0..f0f70cb6c1881 100644 --- a/src/test/rustdoc/primitive/no_std.rs +++ b/src/test/rustdoc/primitive/no_std.rs @@ -1,6 +1,16 @@ #![no_std] +#![deny(warnings)] +#![deny(rustdoc::broken_intra_doc_links)] // @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8' // @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link' /// Link to [primitive link][u8] pub fn foo() -> u8 {} + +// Test that all primitives can be linked to. +/// [isize] [i8] [i16] [i32] [i64] [i128] +/// [usize] [u8] [u16] [u32] [u64] [u128] +/// [f32] [f64] +/// [char] [bool] [str] [slice] [array] [tuple] [unit] +/// [pointer] [reference] [fn] [never] +pub fn bar() {} diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 8cbe0a0c2e8e1..94ebbb33e8d8f 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -30,6 +30,7 @@ use regex::Regex; // If at all possible you should use intra-doc links to avoid linkcheck issues. These // are cases where that does not work // [(generated_documentation_page, &[broken_links])] +#[rustfmt::skip] const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ // These try to link to std::collections, but are defined in alloc // https://github.com/rust-lang/rust/issues/74481 @@ -37,6 +38,19 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ ("std/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]), ("alloc/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]), ("alloc/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]), + + // These try to link to various things in std, but are defined in core. + // The docs in std::primitive use proper intra-doc links, so these seem fine to special-case. + // Most these are broken because liballoc uses `#[lang_item]` magic to define things on + // primitives that aren't available in core. + ("alloc/slice/trait.Join.html", &["#method.join"]), + ("alloc/slice/trait.Concat.html", &["#method.concat"]), + ("alloc/slice/index.html", &["#method.concat", "#method.join"]), + ("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]), + ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]), + ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase", + "core/slice::sort_by_key", "core\\slice::sort_by_key", + "#method.sort_by_cached_key"]), ]; #[rustfmt::skip] @@ -376,6 +390,10 @@ impl Checker { /// Load a file from disk, or from the cache if available. fn load_file(&mut self, file: &Path, report: &mut Report) -> (String, &FileEntry) { + // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- + #[cfg(windows)] + const ERROR_INVALID_NAME: i32 = 123; + let pretty_path = file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string(); @@ -392,6 +410,14 @@ impl Checker { } Err(e) if e.kind() == ErrorKind::NotFound => FileEntry::Missing, Err(e) => { + // If a broken intra-doc link contains `::`, on windows, it will cause `ERROR_INVALID_NAME` rather than `NotFound`. + // Explicitly check for that so that the broken link can be allowed in `LINKCHECK_EXCEPTIONS`. + #[cfg(windows)] + if e.raw_os_error() == Some(ERROR_INVALID_NAME) + && file.as_os_str().to_str().map_or(false, |s| s.contains("::")) + { + return FileEntry::Missing; + } panic!("unexpected read error for {}: {}", file.display(), e); } });