about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/util.rs1
-rw-r--r--library/alloc/src/collections/binary_heap.rs21
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/core/src/num/mod.rs26
-rw-r--r--library/core/src/slice/ascii.rs92
-rw-r--r--library/core/src/slice/mod.rs3
-rw-r--r--library/std/src/sys/unix/ext/net/ancillary.rs57
-rw-r--r--src/librustdoc/html/markdown.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs90
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs13
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr45
-rw-r--r--src/test/ui/const-generics/defaults/complex-unord-param.rs18
-rw-r--r--src/test/ui/const-generics/defaults/default-annotation.rs4
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.rs24
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.stderr50
-rw-r--r--src/test/ui/const-generics/defaults/needs-feature.rs2
-rw-r--r--src/test/ui/const-generics/defaults/repr-c-issue-82792.rs14
-rw-r--r--src/test/ui/const-generics/defaults/simple-defaults.rs6
m---------src/tools/rust-analyzer37
19 files changed, 387 insertions, 118 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 9926cca2f51..9c7de250c29 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -699,7 +699,6 @@ impl<'tcx> ty::TyS<'tcx> {
     /// optimization as well as the rules around static values. Note
     /// that the `Freeze` trait is not exposed to end users and is
     /// effectively an implementation detail.
-    // FIXME: use `TyCtxtAt` instead of separate `Span`.
     pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
         self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self))
     }
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index b5e66d37ab4..bf9f7432fb5 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -958,6 +958,27 @@ impl<T> BinaryHeap<T> {
         self.data.shrink_to(min_capacity)
     }
 
+    /// Returns a slice of all values in the underlying vector, in arbitrary
+    /// order.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(binary_heap_as_slice)]
+    /// use std::collections::BinaryHeap;
+    /// use std::io::{self, Write};
+    ///
+    /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]);
+    ///
+    /// io::sink().write(heap.as_slice()).unwrap();
+    /// ```
+    #[unstable(feature = "binary_heap_as_slice", issue = "83659")]
+    pub fn as_slice(&self) -> &[T] {
+        self.data.as_slice()
+    }
+
     /// Consumes the `BinaryHeap` and returns the underlying vector
     /// in arbitrary order.
     ///
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index c75a6c1f619..7e1194cc4aa 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -14,6 +14,7 @@
 #![feature(binary_heap_drain_sorted)]
 #![feature(slice_ptr_get)]
 #![feature(binary_heap_retain)]
+#![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
 #![feature(vecdeque_binary_search)]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f0bd976ba83..6032dc9a2d3 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -2,6 +2,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use crate::ascii;
 use crate::intrinsics;
 use crate::mem;
 use crate::str::FromStr;
@@ -661,6 +662,31 @@ impl u8 {
     pub const fn is_ascii_control(&self) -> bool {
         matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
     }
+
+    /// Returns an iterator that produces an escaped version of a `u8`,
+    /// treating it as an ASCII character.
+    ///
+    /// The behavior is identical to [`ascii::escape_default`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inherent_ascii_escape)]
+    ///
+    /// assert_eq!("0", b'0'.escape_ascii().to_string());
+    /// assert_eq!("\\t", b'\t'.escape_ascii().to_string());
+    /// assert_eq!("\\r", b'\r'.escape_ascii().to_string());
+    /// assert_eq!("\\n", b'\n'.escape_ascii().to_string());
+    /// assert_eq!("\\'", b'\''.escape_ascii().to_string());
+    /// assert_eq!("\\\"", b'"'.escape_ascii().to_string());
+    /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string());
+    /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string());
+    /// ```
+    #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+    #[inline]
+    pub fn escape_ascii(&self) -> ascii::EscapeDefault {
+        ascii::escape_default(*self)
+    }
 }
 
 #[lang = "u16"]
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 009ef9e0a9c..22fa08b9795 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -1,7 +1,10 @@
 //! Operations on ASCII `[u8]`.
 
+use crate::ascii;
+use crate::fmt::{self, Write};
 use crate::iter;
 use crate::mem;
+use crate::ops;
 
 #[lang = "slice_u8"]
 #[cfg(not(test))]
@@ -56,6 +59,95 @@ impl [u8] {
             byte.make_ascii_lowercase();
         }
     }
+
+    /// Returns an iterator that produces an escaped version of this slice,
+    /// treating it as an ASCII string.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inherent_ascii_escape)]
+    ///
+    /// let s = b"0\t\r\n'\"\\\x9d";
+    /// let escaped = s.escape_ascii().to_string();
+    /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");
+    /// ```
+    #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+    pub fn escape_ascii(&self) -> EscapeAscii<'_> {
+        EscapeAscii { inner: self.iter().flat_map(EscapeByte) }
+    }
+}
+
+impl_fn_for_zst! {
+    #[derive(Clone)]
+    struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {
+        ascii::escape_default(*byte)
+    };
+}
+
+/// An iterator over the escaped version of a byte slice.
+///
+/// This `struct` is created by the [`slice::escape_ascii`] method. See its
+/// documentation for more information.
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+#[derive(Clone)]
+pub struct EscapeAscii<'a> {
+    inner: iter::FlatMap<super::Iter<'a, u8>, ascii::EscapeDefault, EscapeByte>,
+}
+
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::Iterator for EscapeAscii<'a> {
+    type Item = u8;
+    #[inline]
+    fn next(&mut self) -> Option<u8> {
+        self.inner.next()
+    }
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: ops::Try<Ok = Acc>,
+    {
+        self.inner.try_fold(init, fold)
+    }
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.inner.fold(init, fold)
+    }
+    #[inline]
+    fn last(mut self) -> Option<u8> {
+        self.next_back()
+    }
+}
+
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> {
+    fn next_back(&mut self) -> Option<u8> {
+        self.inner.next_back()
+    }
+}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::FusedIterator for EscapeAscii<'a> {}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> fmt::Display for EscapeAscii<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.clone().try_for_each(|b| f.write_char(b as char))
+    }
+}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> fmt::Debug for EscapeAscii<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.pad("EscapeAscii { .. }")
+    }
 }
 
 /// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index d7a28c8d08f..59fad8c813c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -81,6 +81,9 @@ pub use index::SliceIndex;
 #[unstable(feature = "slice_range", issue = "76393")]
 pub use index::range;
 
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+pub use ascii::EscapeAscii;
+
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs
index 33d6a39af07..011ae643f87 100644
--- a/library/std/src/sys/unix/ext/net/ancillary.rs
+++ b/library/std/src/sys/unix/ext/net/ancillary.rs
@@ -5,9 +5,7 @@ use crate::marker::PhantomData;
 use crate::mem::{size_of, zeroed};
 use crate::os::unix::io::RawFd;
 use crate::path::Path;
-#[cfg(target_os = "android")]
-use crate::ptr::eq;
-use crate::ptr::read_unaligned;
+use crate::ptr::{eq, read_unaligned};
 use crate::slice::from_raw_parts;
 use crate::sys::net::Socket;
 
@@ -30,12 +28,10 @@ pub(super) fn recv_vectored_with_ancillary_from(
 ) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
     unsafe {
         let mut msg_name: libc::sockaddr_un = zeroed();
-
         let mut msg: libc::msghdr = zeroed();
         msg.msg_name = &mut msg_name as *mut _ as *mut _;
         msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
         msg.msg_iov = bufs.as_mut_ptr().cast();
-        msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
         cfg_if::cfg_if! {
             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
                 msg.msg_iovlen = bufs.len() as libc::size_t;
@@ -45,6 +41,7 @@ pub(super) fn recv_vectored_with_ancillary_from(
                           target_os = "emscripten",
                           target_os = "freebsd",
                           all(target_os = "linux", target_env = "musl",),
+                          target_os = "macos",
                           target_os = "netbsd",
                           target_os = "openbsd",
                       ))] {
@@ -52,6 +49,10 @@ pub(super) fn recv_vectored_with_ancillary_from(
                 msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t;
             }
         }
+        // macos requires that the control pointer is NULL when the len is 0.
+        if msg.msg_controllen > 0 {
+            msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
+        }
 
         let count = socket.recv_msg(&mut msg)?;
 
@@ -79,7 +80,6 @@ pub(super) fn send_vectored_with_ancillary_to(
         msg.msg_name = &mut msg_name as *mut _ as *mut _;
         msg.msg_namelen = msg_namelen;
         msg.msg_iov = bufs.as_ptr() as *mut _;
-        msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
         cfg_if::cfg_if! {
             if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
                 msg.msg_iovlen = bufs.len() as libc::size_t;
@@ -89,6 +89,7 @@ pub(super) fn send_vectored_with_ancillary_to(
                           target_os = "emscripten",
                           target_os = "freebsd",
                           all(target_os = "linux", target_env = "musl",),
+                          target_os = "macos",
                           target_os = "netbsd",
                           target_os = "openbsd",
                       ))] {
@@ -96,6 +97,10 @@ pub(super) fn send_vectored_with_ancillary_to(
                 msg.msg_controllen = ancillary.length as libc::socklen_t;
             }
         }
+        // macos requires that the control pointer is NULL when the len is 0.
+        if msg.msg_controllen > 0 {
+            msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
+        }
 
         ancillary.truncated = false;
 
@@ -147,6 +152,7 @@ fn add_to_ancillary_data<T>(
                           target_os = "emscripten",
                           target_os = "freebsd",
                           all(target_os = "linux", target_env = "musl",),
+                          target_os = "macos",
                           target_os = "netbsd",
                           target_os = "openbsd",
                       ))] {
@@ -159,14 +165,12 @@ fn add_to_ancillary_data<T>(
         while !cmsg.is_null() {
             previous_cmsg = cmsg;
             cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
-            cfg_if::cfg_if! {
-                // Android return the same pointer if it is the last cmsg.
-                // Therefore, check it if the previous pointer is the same as the current one.
-                if #[cfg(target_os = "android")] {
-                    if cmsg == previous_cmsg {
-                        break;
-                    }
-                }
+
+            // Most operating systems, but not Linux or emscripten, return the previous pointer
+            // when its length is zero. Therefore, check if the previous pointer is the same as
+            // the current one.
+            if eq(cmsg, previous_cmsg) {
+                break;
             }
         }
 
@@ -184,6 +188,7 @@ fn add_to_ancillary_data<T>(
                           target_os = "emscripten",
                           target_os = "freebsd",
                           all(target_os = "linux", target_env = "musl",),
+                          target_os = "macos",
                           target_os = "netbsd",
                           target_os = "openbsd",
                       ))] {
@@ -371,6 +376,7 @@ impl<'a> AncillaryData<'a> {
                               target_os = "emscripten",
                               target_os = "freebsd",
                               all(target_os = "linux", target_env = "musl",),
+                              target_os = "macos",
                               target_os = "netbsd",
                               target_os = "openbsd",
                           ))] {
@@ -421,6 +427,7 @@ impl<'a> Iterator for Messages<'a> {
                               target_os = "emscripten",
                               target_os = "freebsd",
                               all(target_os = "linux", target_env = "musl",),
+                              target_os = "macos",
                               target_os = "netbsd",
                               target_os = "openbsd",
                           ))] {
@@ -435,15 +442,13 @@ impl<'a> Iterator for Messages<'a> {
             };
 
             let cmsg = cmsg.as_ref()?;
-            cfg_if::cfg_if! {
-                // Android return the same pointer if it is the last cmsg.
-                // Therefore, check it if the previous pointer is the same as the current one.
-                if #[cfg(target_os = "android")] {
-                    if let Some(current) = self.current {
-                        if eq(current, cmsg) {
-                            return None;
-                        }
-                    }
+
+            // Most operating systems, but not Linux or emscripten, return the previous pointer
+            // when its length is zero. Therefore, check if the previous pointer is the same as
+            // the current one.
+            if let Some(current) = self.current {
+                if eq(current, cmsg) {
+                    return None;
                 }
             }
 
@@ -514,6 +519,12 @@ impl<'a> SocketAncillary<'a> {
         self.buffer.len()
     }
 
+    /// Returns `true` if the ancillary data is empty.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn is_empty(&self) -> bool {
+        self.length == 0
+    }
+
     /// Returns the number of used bytes.
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     pub fn len(&self) -> usize {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b39f9f87892..c44514ed3cb 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1162,6 +1162,7 @@ crate fn plain_text_summary(md: &str) -> String {
     s
 }
 
+#[derive(Debug)]
 crate struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 499931f7e96..55978ca551b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -950,6 +950,7 @@ impl LinkCollector<'_, '_> {
         }
 
         let link = ori_link.link.replace("`", "");
+        let no_backticks_range = range_between_backticks(&ori_link);
         let parts = link.split('#').collect::<Vec<_>>();
         let (link, extra_fragment) = if parts.len() > 2 {
             // A valid link can't have multiple #'s
@@ -973,10 +974,15 @@ impl LinkCollector<'_, '_> {
         };
 
         // Parse and strip the disambiguator from the link, if present.
-        let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) {
-            (path.trim(), Some(d))
-        } else {
-            (link.trim(), None)
+        let (mut path_str, disambiguator) = match Disambiguator::from_str(&link) {
+            Ok(Some((d, path))) => (path.trim(), Some(d)),
+            Ok(None) => (link.trim(), None),
+            Err((err_msg, relative_range)) => {
+                let disambiguator_range = (no_backticks_range.start + relative_range.start)
+                    ..(no_backticks_range.start + relative_range.end);
+                disambiguator_error(self.cx, &item, dox, disambiguator_range, &err_msg);
+                return None;
+            }
         };
 
         if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;".contains(ch))) {
@@ -1488,6 +1494,27 @@ impl LinkCollector<'_, '_> {
     }
 }
 
+/// Get the section of a link between the backticks,
+/// or the whole link if there aren't any backticks.
+///
+/// For example:
+///
+/// ```text
+/// [`Foo`]
+///   ^^^
+/// ```
+fn range_between_backticks(ori_link: &MarkdownLink) -> Range<usize> {
+    let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0);
+    let before_second_backtick_group = ori_link
+        .link
+        .bytes()
+        .skip(after_first_backtick_group)
+        .position(|b| b == b'`')
+        .unwrap_or(ori_link.link.len());
+    (ori_link.range.start + after_first_backtick_group)
+        ..(ori_link.range.start + before_second_backtick_group)
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 /// Disambiguators for a link.
 enum Disambiguator {
@@ -1514,27 +1541,14 @@ impl Disambiguator {
         }
     }
 
-    /// Given a link, parse and return `(disambiguator, path_str)`
-    fn from_str(link: &str) -> Result<(Self, &str), ()> {
+    /// Given a link, parse and return `(disambiguator, path_str)`.
+    ///
+    /// This returns `Ok(Some(...))` if a disambiguator was found,
+    /// `Ok(None)` if no disambiguator was found, or `Err(...)`
+    /// if there was a problem with the disambiguator.
+    fn from_str(link: &str) -> Result<Option<(Self, &str)>, (String, Range<usize>)> {
         use Disambiguator::{Kind, Namespace as NS, Primitive};
 
-        let find_suffix = || {
-            let suffixes = [
-                ("!()", DefKind::Macro(MacroKind::Bang)),
-                ("()", DefKind::Fn),
-                ("!", DefKind::Macro(MacroKind::Bang)),
-            ];
-            for &(suffix, kind) in &suffixes {
-                if let Some(link) = link.strip_suffix(suffix) {
-                    // Avoid turning `!` or `()` into an empty string
-                    if !link.is_empty() {
-                        return Ok((Kind(kind), link));
-                    }
-                }
-            }
-            Err(())
-        };
-
         if let Some(idx) = link.find('@') {
             let (prefix, rest) = link.split_at(idx);
             let d = match prefix {
@@ -1551,11 +1565,24 @@ impl Disambiguator {
                 "value" => NS(Namespace::ValueNS),
                 "macro" => NS(Namespace::MacroNS),
                 "prim" | "primitive" => Primitive,
-                _ => return find_suffix(),
+                _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)),
             };
-            Ok((d, &rest[1..]))
+            Ok(Some((d, &rest[1..])))
         } else {
-            find_suffix()
+            let suffixes = [
+                ("!()", DefKind::Macro(MacroKind::Bang)),
+                ("()", DefKind::Fn),
+                ("!", DefKind::Macro(MacroKind::Bang)),
+            ];
+            for &(suffix, kind) in &suffixes {
+                if let Some(link) = link.strip_suffix(suffix) {
+                    // Avoid turning `!` or `()` into an empty string
+                    if !link.is_empty() {
+                        return Ok(Some((Kind(kind), link)));
+                    }
+                }
+            }
+            Ok(None)
         }
     }
 
@@ -1979,6 +2006,17 @@ fn anchor_failure(
     });
 }
 
+/// Report an error in the link disambiguator.
+fn disambiguator_error(
+    cx: &DocContext<'_>,
+    item: &Item,
+    dox: &str,
+    link_range: Range<usize>,
+    msg: &str,
+) {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, item, dox, &link_range, |_diag, _sp| {});
+}
+
 /// Report an ambiguity error, where there were multiple possible resolutions.
 fn ambiguity_error(
     cx: &DocContext<'_>,
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
new file mode 100644
index 00000000000..925fc515a3e
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
@@ -0,0 +1,13 @@
+#![deny(warnings)]
+
+//! Linking to [foo@banana] and [`bar@banana!()`].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `bar`
+//! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+//~^ ERROR unknown disambiguator ``
+//~| ERROR unknown disambiguator ``
+//! And with weird backticks: [``foo@hello``] [foo`@`hello].
+//~^ ERROR unknown disambiguator `foo`
+//~| ERROR unknown disambiguator `foo`
+
+fn main() {}
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
new file mode 100644
index 00000000000..195aaca32a2
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -0,0 +1,45 @@
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:3:17
+   |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+   |                 ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unknown-disambiguator.rs:1:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+
+error: unknown disambiguator `bar`
+  --> $DIR/unknown-disambiguator.rs:3:35
+   |
+LL | //! Linking to [foo@banana] and [`bar@banana!()`].
+   |                                   ^^^
+
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:9:34
+   |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+   |                                  ^^^
+
+error: unknown disambiguator `foo`
+  --> $DIR/unknown-disambiguator.rs:9:48
+   |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+   |                                                ^^^
+
+error: unknown disambiguator ``
+  --> $DIR/unknown-disambiguator.rs:6:31
+   |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+   |                               ^
+
+error: unknown disambiguator ``
+  --> $DIR/unknown-disambiguator.rs:6:57
+   |
+LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
+   |                                                         ^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/const-generics/defaults/complex-unord-param.rs b/src/test/ui/const-generics/defaults/complex-unord-param.rs
index 82b3627d22f..d24e403e017 100644
--- a/src/test/ui/const-generics/defaults/complex-unord-param.rs
+++ b/src/test/ui/const-generics/defaults/complex-unord-param.rs
@@ -6,16 +6,16 @@
 #![allow(dead_code)]
 
 struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
-  //[min]~^ ERROR type parameters must be declared prior to const parameters
-  args: &'a [&'a [T; M]; N],
-  specifier: A,
+    //[min]~^ ERROR type parameters must be declared prior to const parameters
+    args: &'a [&'a [T; M]; N],
+    specifier: A,
 }
 
 fn main() {
-  let array = [1, 2, 3];
-  let nest = [&array];
-  let _ = NestedArrays {
-    args: &nest,
-    specifier: true,
-  };
+    let array = [1, 2, 3];
+    let nest = [&array];
+    let _ = NestedArrays {
+        args: &nest,
+        specifier: true,
+    };
 }
diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs
index e6e8d732bee..3febb7cffbf 100644
--- a/src/test/ui/const-generics/defaults/default-annotation.rs
+++ b/src/test/ui/const-generics/defaults/default-annotation.rs
@@ -13,8 +13,8 @@ pub struct ConstDefaultUnstable<const N: usize = 3>;
 
 #[stable(feature = "const_default_unstable", since="none")]
 pub struct ConstDefaultStable<const N: usize = {
-  #[stable(feature = "const_default_unstable_val", since="none")]
-  3
+    #[stable(feature = "const_default_unstable_val", since="none")]
+    3
 }>;
 
 fn main() {}
diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs
index bf578468bb6..d85b756f538 100644
--- a/src/test/ui/const-generics/defaults/mismatch.rs
+++ b/src/test/ui/const-generics/defaults/mismatch.rs
@@ -8,16 +8,16 @@ pub struct Example3<const N: usize=13, T=u32>(T);
 pub struct Example4<const N: usize=13, const M: usize=4>;
 
 fn main() {
-  let e: Example::<13> = ();
-  //~^ Error: mismatched types
-  let e: Example2::<u32, 13> = ();
-  //~^ Error: mismatched types
-  let e: Example3::<13, u32> = ();
-  //~^ Error: mismatched types
-  let e: Example3::<7> = ();
-  //~^ Error: mismatched types
-  // FIXME(const_generics_defaults): There should be a note for the error below, but it is
-  // missing.
-  let e: Example4::<7> = ();
-  //~^ Error: mismatched types
+    let e: Example::<13> = ();
+    //~^ Error: mismatched types
+    let e: Example2::<u32, 13> = ();
+    //~^ Error: mismatched types
+    let e: Example3::<13, u32> = ();
+    //~^ Error: mismatched types
+    let e: Example3::<7> = ();
+    //~^ Error: mismatched types
+    // FIXME(const_generics_defaults): There should be a note for the error below, but it is
+    // missing.
+    let e: Example4::<7> = ();
+    //~^ Error: mismatched types
 }
diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr
index c66eb4cd645..ff72c71c40f 100644
--- a/src/test/ui/const-generics/defaults/mismatch.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.stderr
@@ -1,51 +1,51 @@
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:11:26
+  --> $DIR/mismatch.rs:11:28
    |
-LL |   let e: Example::<13> = ();
-   |          -------------   ^^ expected struct `Example`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example::<13> = ();
+   |            -------------   ^^ expected struct `Example`, found `()`
+   |            |
+   |            expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:13:32
+  --> $DIR/mismatch.rs:13:34
    |
-LL |   let e: Example2::<u32, 13> = ();
-   |          -------------------   ^^ expected struct `Example2`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example2::<u32, 13> = ();
+   |            -------------------   ^^ expected struct `Example2`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example2`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:32
+  --> $DIR/mismatch.rs:15:34
    |
-LL |   let e: Example3::<13, u32> = ();
-   |          -------------------   ^^ expected struct `Example3`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example3::<13, u32> = ();
+   |            -------------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example3`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:17:26
+  --> $DIR/mismatch.rs:17:28
    |
-LL |   let e: Example3::<7> = ();
-   |          -------------   ^^ expected struct `Example3`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example3::<7> = ();
+   |            -------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
    |
    = note: expected struct `Example3<7_usize>`
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:26
+  --> $DIR/mismatch.rs:21:28
    |
-LL |   let e: Example4::<7> = ();
-   |          -------------   ^^ expected struct `Example4`, found `()`
-   |          |
-   |          expected due to this
+LL |     let e: Example4::<7> = ();
+   |            -------------   ^^ expected struct `Example4`, found `()`
+   |            |
+   |            expected due to this
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/needs-feature.rs b/src/test/ui/const-generics/defaults/needs-feature.rs
index 7eb7764a644..b58dee0712a 100644
--- a/src/test/ui/const-generics/defaults/needs-feature.rs
+++ b/src/test/ui/const-generics/defaults/needs-feature.rs
@@ -10,5 +10,5 @@ struct A<const N: usize, T=u32>(T);
 //[min]~^ ERROR type parameters must be declared prior
 
 fn main() {
-  let _: A<3> = A(0);
+    let _: A<3> = A(0);
 }
diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
new file mode 100644
index 00000000000..18ecf467299
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -0,0 +1,14 @@
+// Regression test for #82792.
+
+// run-pass
+
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+#[repr(C)]
+pub struct Loaf<T: Sized, const N: usize = 1usize> {
+    head: [T; N],
+    slice: [T],
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs
index 1f1b6c2260d..cb66c7769bb 100644
--- a/src/test/ui/const-generics/defaults/simple-defaults.rs
+++ b/src/test/ui/const-generics/defaults/simple-defaults.rs
@@ -6,12 +6,12 @@
 #![allow(dead_code)]
 
 struct FixedOutput<'a, const N: usize, T=u32> {
-  //[min]~^ ERROR type parameters must be declared prior to const parameters
-  out: &'a [T; N],
+    //[min]~^ ERROR type parameters must be declared prior to const parameters
+    out: &'a [T; N],
 }
 
 trait FixedOutputter {
-  fn out(&self) -> FixedOutput<'_, 10>;
+    fn out(&self) -> FixedOutput<'_, 10>;
 }
 
 fn main() {}
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 858ad554374a8b1ad67692558a0878391abfdd8
+Subproject bb1d925dab36372c6bd1fb5671bb68ce938ff00