mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 05:53:10 +00:00
Auto merge of #83664 - Dylan-DPC:rollup-wx6idpd, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #82331 (alloc: Added `as_slice` method to `BinaryHeap` collection) - #83130 (escape_ascii take 2) - #83374 (unix: Fix feature(unix_socket_ancillary_data) on macos and other BSDs) - #83543 (Lint on unknown intra-doc link disambiguators) - #83636 (Add a regression test for issue-82792) - #83643 (Remove a FIXME resolved by #73578) - #83644 (⬆️ rust-analyzer) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
902ca44c19
@ -699,7 +699,6 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||||||
/// optimization as well as the rules around static values. Note
|
/// optimization as well as the rules around static values. Note
|
||||||
/// that the `Freeze` trait is not exposed to end users and is
|
/// that the `Freeze` trait is not exposed to end users and is
|
||||||
/// effectively an implementation detail.
|
/// 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 {
|
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))
|
self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self))
|
||||||
}
|
}
|
||||||
|
@ -958,6 +958,27 @@ impl<T> BinaryHeap<T> {
|
|||||||
self.data.shrink_to(min_capacity)
|
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
|
/// Consumes the `BinaryHeap` and returns the underlying vector
|
||||||
/// in arbitrary order.
|
/// in arbitrary order.
|
||||||
///
|
///
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#![feature(binary_heap_drain_sorted)]
|
#![feature(binary_heap_drain_sorted)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(binary_heap_retain)]
|
#![feature(binary_heap_retain)]
|
||||||
|
#![feature(binary_heap_as_slice)]
|
||||||
#![feature(inplace_iteration)]
|
#![feature(inplace_iteration)]
|
||||||
#![feature(iter_map_while)]
|
#![feature(iter_map_while)]
|
||||||
#![feature(vecdeque_binary_search)]
|
#![feature(vecdeque_binary_search)]
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
use crate::ascii;
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::str::FromStr;
|
use crate::str::FromStr;
|
||||||
@ -661,6 +662,31 @@ impl u8 {
|
|||||||
pub const fn is_ascii_control(&self) -> bool {
|
pub const fn is_ascii_control(&self) -> bool {
|
||||||
matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
|
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"]
|
#[lang = "u16"]
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
//! Operations on ASCII `[u8]`.
|
//! Operations on ASCII `[u8]`.
|
||||||
|
|
||||||
|
use crate::ascii;
|
||||||
|
use crate::fmt::{self, Write};
|
||||||
use crate::iter;
|
use crate::iter;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
|
use crate::ops;
|
||||||
|
|
||||||
#[lang = "slice_u8"]
|
#[lang = "slice_u8"]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
@ -56,6 +59,95 @@ impl [u8] {
|
|||||||
byte.make_ascii_lowercase();
|
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
|
/// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed
|
||||||
|
@ -81,6 +81,9 @@ pub use index::SliceIndex;
|
|||||||
#[unstable(feature = "slice_range", issue = "76393")]
|
#[unstable(feature = "slice_range", issue = "76393")]
|
||||||
pub use index::range;
|
pub use index::range;
|
||||||
|
|
||||||
|
#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
|
||||||
|
pub use ascii::EscapeAscii;
|
||||||
|
|
||||||
#[lang = "slice"]
|
#[lang = "slice"]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl<T> [T] {
|
impl<T> [T] {
|
||||||
|
@ -5,9 +5,7 @@ use crate::marker::PhantomData;
|
|||||||
use crate::mem::{size_of, zeroed};
|
use crate::mem::{size_of, zeroed};
|
||||||
use crate::os::unix::io::RawFd;
|
use crate::os::unix::io::RawFd;
|
||||||
use crate::path::Path;
|
use crate::path::Path;
|
||||||
#[cfg(target_os = "android")]
|
use crate::ptr::{eq, read_unaligned};
|
||||||
use crate::ptr::eq;
|
|
||||||
use crate::ptr::read_unaligned;
|
|
||||||
use crate::slice::from_raw_parts;
|
use crate::slice::from_raw_parts;
|
||||||
use crate::sys::net::Socket;
|
use crate::sys::net::Socket;
|
||||||
|
|
||||||
@ -30,12 +28,10 @@ pub(super) fn recv_vectored_with_ancillary_from(
|
|||||||
) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
|
) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut msg_name: libc::sockaddr_un = zeroed();
|
let mut msg_name: libc::sockaddr_un = zeroed();
|
||||||
|
|
||||||
let mut msg: libc::msghdr = zeroed();
|
let mut msg: libc::msghdr = zeroed();
|
||||||
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
msg.msg_name = &mut msg_name as *mut _ as *mut _;
|
||||||
msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
|
msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
|
||||||
msg.msg_iov = bufs.as_mut_ptr().cast();
|
msg.msg_iov = bufs.as_mut_ptr().cast();
|
||||||
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
||||||
msg.msg_iovlen = bufs.len() as libc::size_t;
|
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 = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
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;
|
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)?;
|
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_name = &mut msg_name as *mut _ as *mut _;
|
||||||
msg.msg_namelen = msg_namelen;
|
msg.msg_namelen = msg_namelen;
|
||||||
msg.msg_iov = bufs.as_ptr() as *mut _;
|
msg.msg_iov = bufs.as_ptr() as *mut _;
|
||||||
msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
|
||||||
msg.msg_iovlen = bufs.len() as libc::size_t;
|
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 = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
))] {
|
))] {
|
||||||
@ -96,6 +97,10 @@ pub(super) fn send_vectored_with_ancillary_to(
|
|||||||
msg.msg_controllen = ancillary.length as libc::socklen_t;
|
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;
|
ancillary.truncated = false;
|
||||||
|
|
||||||
@ -147,6 +152,7 @@ fn add_to_ancillary_data<T>(
|
|||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
))] {
|
))] {
|
||||||
@ -159,16 +165,14 @@ fn add_to_ancillary_data<T>(
|
|||||||
while !cmsg.is_null() {
|
while !cmsg.is_null() {
|
||||||
previous_cmsg = cmsg;
|
previous_cmsg = cmsg;
|
||||||
cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
|
cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
|
||||||
cfg_if::cfg_if! {
|
|
||||||
// Android return the same pointer if it is the last cmsg.
|
// Most operating systems, but not Linux or emscripten, return the previous pointer
|
||||||
// Therefore, check it if the previous pointer is the same as the current one.
|
// when its length is zero. Therefore, check if the previous pointer is the same as
|
||||||
if #[cfg(target_os = "android")] {
|
// the current one.
|
||||||
if cmsg == previous_cmsg {
|
if eq(cmsg, previous_cmsg) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if previous_cmsg.is_null() {
|
if previous_cmsg.is_null() {
|
||||||
return false;
|
return false;
|
||||||
@ -184,6 +188,7 @@ fn add_to_ancillary_data<T>(
|
|||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
))] {
|
))] {
|
||||||
@ -371,6 +376,7 @@ impl<'a> AncillaryData<'a> {
|
|||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
))] {
|
))] {
|
||||||
@ -421,6 +427,7 @@ impl<'a> Iterator for Messages<'a> {
|
|||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "musl",),
|
all(target_os = "linux", target_env = "musl",),
|
||||||
|
target_os = "macos",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
))] {
|
))] {
|
||||||
@ -435,17 +442,15 @@ impl<'a> Iterator for Messages<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let cmsg = cmsg.as_ref()?;
|
let cmsg = cmsg.as_ref()?;
|
||||||
cfg_if::cfg_if! {
|
|
||||||
// Android return the same pointer if it is the last cmsg.
|
// Most operating systems, but not Linux or emscripten, return the previous pointer
|
||||||
// Therefore, check it if the previous pointer is the same as the current one.
|
// when its length is zero. Therefore, check if the previous pointer is the same as
|
||||||
if #[cfg(target_os = "android")] {
|
// the current one.
|
||||||
if let Some(current) = self.current {
|
if let Some(current) = self.current {
|
||||||
if eq(current, cmsg) {
|
if eq(current, cmsg) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current = Some(cmsg);
|
self.current = Some(cmsg);
|
||||||
let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg);
|
let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg);
|
||||||
@ -514,6 +519,12 @@ impl<'a> SocketAncillary<'a> {
|
|||||||
self.buffer.len()
|
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.
|
/// Returns the number of used bytes.
|
||||||
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
|
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
|
@ -1162,6 +1162,7 @@ crate fn plain_text_summary(md: &str) -> String {
|
|||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
crate struct MarkdownLink {
|
crate struct MarkdownLink {
|
||||||
pub kind: LinkType,
|
pub kind: LinkType,
|
||||||
pub link: String,
|
pub link: String,
|
||||||
|
@ -950,6 +950,7 @@ impl LinkCollector<'_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let link = ori_link.link.replace("`", "");
|
let link = ori_link.link.replace("`", "");
|
||||||
|
let no_backticks_range = range_between_backticks(&ori_link);
|
||||||
let parts = link.split('#').collect::<Vec<_>>();
|
let parts = link.split('#').collect::<Vec<_>>();
|
||||||
let (link, extra_fragment) = if parts.len() > 2 {
|
let (link, extra_fragment) = if parts.len() > 2 {
|
||||||
// A valid link can't have multiple #'s
|
// A valid link can't have multiple #'s
|
||||||
@ -973,10 +974,15 @@ impl LinkCollector<'_, '_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parse and strip the disambiguator from the link, if present.
|
// Parse and strip the disambiguator from the link, if present.
|
||||||
let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) {
|
let (mut path_str, disambiguator) = match Disambiguator::from_str(&link) {
|
||||||
(path.trim(), Some(d))
|
Ok(Some((d, path))) => (path.trim(), Some(d)),
|
||||||
} else {
|
Ok(None) => (link.trim(), 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))) {
|
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)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
/// Disambiguators for a link.
|
/// Disambiguators for a link.
|
||||||
enum Disambiguator {
|
enum Disambiguator {
|
||||||
@ -1514,27 +1541,14 @@ impl Disambiguator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a link, parse and return `(disambiguator, path_str)`
|
/// Given a link, parse and return `(disambiguator, path_str)`.
|
||||||
fn from_str(link: &str) -> Result<(Self, &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};
|
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('@') {
|
if let Some(idx) = link.find('@') {
|
||||||
let (prefix, rest) = link.split_at(idx);
|
let (prefix, rest) = link.split_at(idx);
|
||||||
let d = match prefix {
|
let d = match prefix {
|
||||||
@ -1551,11 +1565,24 @@ impl Disambiguator {
|
|||||||
"value" => NS(Namespace::ValueNS),
|
"value" => NS(Namespace::ValueNS),
|
||||||
"macro" => NS(Namespace::MacroNS),
|
"macro" => NS(Namespace::MacroNS),
|
||||||
"prim" | "primitive" => Primitive,
|
"prim" | "primitive" => Primitive,
|
||||||
_ => return find_suffix(),
|
_ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)),
|
||||||
};
|
};
|
||||||
Ok((d, &rest[1..]))
|
Ok(Some((d, &rest[1..])))
|
||||||
} else {
|
} 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.
|
/// Report an ambiguity error, where there were multiple possible resolutions.
|
||||||
fn ambiguity_error(
|
fn ambiguity_error(
|
||||||
cx: &DocContext<'_>,
|
cx: &DocContext<'_>,
|
||||||
|
13
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
Normal file
13
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
Normal file
@ -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() {}
|
45
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
Normal file
45
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
Normal file
@ -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
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch.rs:11:26
|
--> $DIR/mismatch.rs:11:28
|
||||||
|
|
|
|
||||||
LL | let e: Example::<13> = ();
|
LL | let e: Example::<13> = ();
|
||||||
| ------------- ^^ expected struct `Example`, found `()`
|
| ------------- ^^ expected struct `Example`, found `()`
|
||||||
@ -7,7 +7,7 @@ LL | let e: Example::<13> = ();
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch.rs:13:32
|
--> $DIR/mismatch.rs:13:34
|
||||||
|
|
|
|
||||||
LL | let e: Example2::<u32, 13> = ();
|
LL | let e: Example2::<u32, 13> = ();
|
||||||
| ------------------- ^^ expected struct `Example2`, found `()`
|
| ------------------- ^^ expected struct `Example2`, found `()`
|
||||||
@ -18,7 +18,7 @@ LL | let e: Example2::<u32, 13> = ();
|
|||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch.rs:15:32
|
--> $DIR/mismatch.rs:15:34
|
||||||
|
|
|
|
||||||
LL | let e: Example3::<13, u32> = ();
|
LL | let e: Example3::<13, u32> = ();
|
||||||
| ------------------- ^^ expected struct `Example3`, found `()`
|
| ------------------- ^^ expected struct `Example3`, found `()`
|
||||||
@ -29,7 +29,7 @@ LL | let e: Example3::<13, u32> = ();
|
|||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch.rs:17:26
|
--> $DIR/mismatch.rs:17:28
|
||||||
|
|
|
|
||||||
LL | let e: Example3::<7> = ();
|
LL | let e: Example3::<7> = ();
|
||||||
| ------------- ^^ expected struct `Example3`, found `()`
|
| ------------- ^^ expected struct `Example3`, found `()`
|
||||||
@ -40,7 +40,7 @@ LL | let e: Example3::<7> = ();
|
|||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mismatch.rs:21:26
|
--> $DIR/mismatch.rs:21:28
|
||||||
|
|
|
|
||||||
LL | let e: Example4::<7> = ();
|
LL | let e: Example4::<7> = ();
|
||||||
| ------------- ^^ expected struct `Example4`, found `()`
|
| ------------- ^^ expected struct `Example4`, found `()`
|
||||||
|
14
src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
Normal file
14
src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
Normal file
@ -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() {}
|
@ -1 +1 @@
|
|||||||
Subproject commit 858ad554374a8b1ad67692558a0878391abfdd86
|
Subproject commit bb1d925dab36372c6bd1fb5671bb68ce938ff009
|
Loading…
Reference in New Issue
Block a user