提交 e674422f 编写于 作者: B bors

Auto merge of #75797 - Dylan-DPC:rollup-lfeytr7, r=Dylan-DPC

Rollup of 12 pull requests

Successful merges:

 - #75705 (Move to intra-doc links for /library/core/src/intrinsics.rs)
 - #75711 (Split `astconv.rs` into its own submodule)
 - #75718 (Don't count variants/fields/consts/associated types in doc-coverage doc examples)
 - #75725 (Use intra-doc-links in `alloc`)
 - #75745 (Remove duplication in `fold_item`)
 - #75753 (Another motivation for CFG: return-oriented programming)
 - #75769 (Minor, remove double nesting of a test module)
 - #75771 (Extend normalization in const-eval-query-stack test)
 - #75781 (More inline asm register name fixups for LLVM)
 - #75782 (Convert core/src/str/pattern.rs to Intra-doc links)
 - #75787 (Use intra-doc-links in `core::ops::*`)
 - #75788 (MIR call terminator represents diverging calls too)

Failed merges:

 - #75773 (Introduce expect snapshot testing library into rustc)

r? @ghost
......@@ -36,8 +36,6 @@
///
/// Note: while this type is unstable, the functionality it provides can be
/// accessed through the [free functions in `alloc`](index.html#functions).
///
/// [`AllocRef`]: trait.AllocRef.html
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Copy, Clone, Default, Debug)]
pub struct Global;
......@@ -55,10 +53,6 @@
///
/// See [`GlobalAlloc::alloc`].
///
/// [`Global`]: struct.Global.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
///
/// # Examples
///
/// ```
......@@ -92,10 +86,6 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
/// # Safety
///
/// See [`GlobalAlloc::dealloc`].
///
/// [`Global`]: struct.Global.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
#[stable(feature = "global_alloc", since = "1.28.0")]
#[inline]
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
......@@ -114,10 +104,6 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
/// # Safety
///
/// See [`GlobalAlloc::realloc`].
///
/// [`Global`]: struct.Global.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
#[stable(feature = "global_alloc", since = "1.28.0")]
#[inline]
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
......@@ -137,10 +123,6 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
///
/// See [`GlobalAlloc::alloc_zeroed`].
///
/// [`Global`]: struct.Global.html
/// [`AllocRef`]: trait.AllocRef.html
/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
///
/// # Examples
///
/// ```
......
......@@ -118,14 +118,13 @@
//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
//!
//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
//! [dereferencing]: ../../std/ops/trait.Deref.html
//! [`Box`]: struct.Box.html
//! [`Box<T>`]: struct.Box.html
//! [`Box::<T>::from_raw(value)`]: struct.Box.html#method.from_raw
//! [`Box::<T>::into_raw`]: struct.Box.html#method.into_raw
//! [`Global`]: ../alloc/struct.Global.html
//! [`Layout`]: ../alloc/struct.Layout.html
//! [`Layout::for_value(&*value)`]: ../alloc/struct.Layout.html#method.for_value
//! [dereferencing]: core::ops::Deref
//! [`Box<T>`]: Box
//! [`Box::<T>::from_raw(value)`]: Box::from_raw
//! [`Box::<T>::into_raw`]: Box::into_raw
//! [`Global`]: crate::alloc::Global
//! [`Layout`]: crate::alloc::Layout
//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
#![stable(feature = "rust1", since = "1.0.0")]
......@@ -240,7 +239,6 @@ pub fn pin(x: T) -> Pin<Box<T>> {
/// Converts a `Box<T>` into a `Box<[T]>`
///
/// This conversion does not allocate on the heap and happens in place.
///
#[unstable(feature = "box_into_boxed_slice", issue = "71582")]
pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
// *mut T and *mut [T; 1] have the same size and alignment
......@@ -386,9 +384,8 @@ impl<T: ?Sized> Box<T> {
/// }
/// ```
///
/// [memory layout]: index.html#memory-layout
/// [`Layout`]: ../alloc/struct.Layout.html
/// [`Box::into_raw`]: struct.Box.html#method.into_raw
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
pub unsafe fn from_raw(raw: *mut T) -> Self {
......@@ -433,8 +430,7 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
/// }
/// ```
///
/// [memory layout]: index.html#memory-layout
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
/// [memory layout]: self#memory-layout
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
pub fn into_raw(b: Box<T>) -> *mut T {
......@@ -478,8 +474,6 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
/// to call it as `Box::leak(b)` instead of `b.leak()`. This
/// is so that there is no conflict with a method on the inner type.
///
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
///
/// # Examples
///
/// Simple usage:
......
......@@ -7,8 +7,8 @@
//! array-based containers are generally faster,
//! more memory efficient, and make better use of CPU cache.
//!
//! [`Vec`]: ../../vec/struct.Vec.html
//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html
//! [`Vec`]: crate::vec::Vec
//! [`VecDeque`]: super::vec_deque::VecDeque
#![stable(feature = "rust1", since = "1.0.0")]
......@@ -50,11 +50,8 @@ struct Node<T> {
/// An iterator over the elements of a `LinkedList`.
///
/// This `struct` is created by the [`iter`] method on [`LinkedList`]. See its
/// This `struct` is created by [`LinkedList::iter()`]. See its
/// documentation for more.
///
/// [`iter`]: struct.LinkedList.html#method.iter
/// [`LinkedList`]: struct.LinkedList.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
head: Option<NonNull<Node<T>>>,
......@@ -80,11 +77,8 @@ fn clone(&self) -> Self {
/// A mutable iterator over the elements of a `LinkedList`.
///
/// This `struct` is created by the [`iter_mut`] method on [`LinkedList`]. See its
/// This `struct` is created by [`LinkedList::iter_mut()`]. See its
/// documentation for more.
///
/// [`iter_mut`]: struct.LinkedList.html#method.iter_mut
/// [`LinkedList`]: struct.LinkedList.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
// We do *not* exclusively own the entire list here, references to node's `element`
......@@ -109,7 +103,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// (provided by the `IntoIterator` trait). See its documentation for more.
///
/// [`into_iter`]: struct.LinkedList.html#method.into_iter
/// [`LinkedList`]: struct.LinkedList.html
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
......
......@@ -501,31 +501,23 @@
//! it would internally pass around this structure until it has been determined
//! where output should go to.
//!
//! [`usize`]: ../../std/primitive.usize.html
//! [`isize`]: ../../std/primitive.isize.html
//! [`i8`]: ../../std/primitive.i8.html
//! [`Display`]: trait.Display.html
//! [`Binary`]: trait.Binary.html
//! [`fmt::Result`]: type.Result.html
//! [`Result`]: ../../std/result/enum.Result.html
//! [`std::fmt::Error`]: struct.Error.html
//! [`Formatter`]: struct.Formatter.html
//! [`write!`]: ../../std/macro.write.html
//! [`Debug`]: trait.Debug.html
//! [`format!`]: ../../std/macro.format.html
//! [`to_string`]: ../../std/string/trait.ToString.html
//! [`writeln!`]: ../../std/macro.writeln.html
//! [`fmt::Result`]: Result
//! [`Result`]: core::result::Result
//! [`std::fmt::Error`]: Error
//! [`write!`]: core::write
//! [`write`]: core::write
//! [`format!`]: crate::format
//! [`to_string`]: crate::string::ToString
//! [`writeln!`]: core::writeln
//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt
//! [`std::io::Write`]: ../../std/io/trait.Write.html
//! [`print!`]: ../../std/macro.print.html
//! [`println!`]: ../../std/macro.println.html
//! [`eprint!`]: ../../std/macro.eprint.html
//! [`eprintln!`]: ../../std/macro.eprintln.html
//! [`write!`]: ../../std/macro.write.html
//! [`format_args!`]: ../../std/macro.format_args.html
//! [`fmt::Arguments`]: struct.Arguments.html
//! [`write`]: fn.write.html
//! [`format`]: fn.format.html
//! [`format_args!`]: core::format_args
//! [`fmt::Arguments`]: Arguments
//! [`format`]: crate::format
#![stable(feature = "rust1", since = "1.0.0")]
......@@ -576,9 +568,8 @@
/// assert_eq!(s, "Hello, world!");
/// ```
///
/// [`Arguments`]: struct.Arguments.html
/// [`format_args!`]: ../../std/macro.format_args.html
/// [`format!`]: ../../std/macro.format.html
/// [`format_args!`]: core::format_args
/// [`format!`]: crate::format
#[stable(feature = "rust1", since = "1.0.0")]
pub fn format(args: Arguments<'_>) -> string::String {
let capacity = args.estimated_capacity();
......
......@@ -50,11 +50,11 @@
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync/index.html
//! [`Box`]: boxed/index.html
//! [`Cell`]: ../core/cell/index.html
//! [`Rc`]: rc/index.html
//! [`RefCell`]: ../core/cell/index.html
//! [`Arc`]: sync
//! [`Box`]: boxed
//! [`Cell`]: core::cell
//! [`Rc`]: rc
//! [`RefCell`]: core::cell
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
......
......@@ -29,8 +29,7 @@
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// [`Vec`]: ../std/vec/struct.Vec.html
/// [`Clone`]: ../std/clone/trait.Clone.html
/// [`Vec`]: crate::vec::Vec
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
......@@ -81,11 +80,11 @@
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [fmt]: ../std/fmt/index.html
/// [fmt]: core::fmt
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: ../std/macro.write.html
/// [`to_string`]: ../std/string/trait.ToString.html
/// [`Display`]: ../std/fmt/trait.Display.html
/// [`write!`]: core::write
/// [`to_string`]: crate::string::ToString
/// [`Display`]: core::fmt::Display
///
/// # Panics
///
......
......@@ -214,18 +214,15 @@
//! }
//! ```
//!
//! [`Rc`]: struct.Rc.html
//! [`Weak`]: struct.Weak.html
//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
//! [`Cell`]: ../../std/cell/struct.Cell.html
//! [`RefCell`]: ../../std/cell/struct.RefCell.html
//! [send]: ../../std/marker/trait.Send.html
//! [clone]: Clone::clone
//! [`Cell`]: core::cell::Cell
//! [`RefCell`]: core::cell::RefCell
//! [send]: core::marker::Send
//! [arc]: ../../std/sync/struct.Arc.html
//! [`Deref`]: ../../std/ops/trait.Deref.html
//! [downgrade]: struct.Rc.html#method.downgrade
//! [upgrade]: struct.Weak.html#method.upgrade
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
//! [`Deref`]: core::ops::Deref
//! [downgrade]: Rc::downgrade
//! [upgrade]: Weak::upgrade
//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
#![stable(feature = "rust1", since = "1.0.0")]
......@@ -396,13 +393,11 @@ pub fn pin(value: T) -> Pin<Rc<T>> {
/// Returns the inner value, if the `Rc` has exactly one strong reference.
///
/// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
/// Otherwise, an [`Err`] is returned with the same `Rc` that was
/// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
/// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// ```
......@@ -553,7 +548,7 @@ impl<T: ?Sized> Rc<T> {
/// To avoid a memory leak the pointer must be converted back to an `Rc` using
/// [`Rc::from_raw`][from_raw].
///
/// [from_raw]: struct.Rc.html#method.from_raw
/// [from_raw]: Rc::from_raw
///
/// # Examples
///
......@@ -613,8 +608,8 @@ pub fn as_ptr(this: &Self) -> *const T {
/// This function is unsafe because improper use may lead to memory unsafety,
/// even if the returned `Rc<T>` is never accessed.
///
/// [into_raw]: struct.Rc.html#method.into_raw
/// [transmute]: ../../std/mem/fn.transmute.html
/// [into_raw]: Rc::into_raw
/// [transmute]: core::mem::transmute
///
/// # Examples
///
......@@ -645,9 +640,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
unsafe { Self::from_ptr(rc_ptr) }
}
/// Creates a new [`Weak`][weak] pointer to this allocation.
///
/// [weak]: struct.Weak.html
/// Creates a new [`Weak`] pointer to this allocation.
///
/// # Examples
///
......@@ -666,9 +659,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
Weak { ptr: this.ptr }
}
/// Gets the number of [`Weak`][weak] pointers to this allocation.
///
/// [weak]: struct.Weak.html
/// Gets the number of [`Weak`] pointers to this allocation.
///
/// # Examples
///
......@@ -704,17 +695,15 @@ pub fn strong_count(this: &Self) -> usize {
this.strong()
}
/// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to
/// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
/// this allocation.
///
/// [weak]: struct.Weak.html
#[inline]
fn is_unique(this: &Self) -> bool {
Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
}
/// Returns a mutable reference into the given `Rc`, if there are
/// no other `Rc` or [`Weak`][weak] pointers to the same allocation.
/// no other `Rc` or [`Weak`] pointers to the same allocation.
///
/// Returns [`None`] otherwise, because it is not safe to
/// mutate a shared value.
......@@ -722,10 +711,8 @@ fn is_unique(this: &Self) -> bool {
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
/// the inner value when there are other pointers.
///
/// [weak]: struct.Weak.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [make_mut]: struct.Rc.html#method.make_mut
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [make_mut]: Rc::make_mut
/// [clone]: Clone::clone
///
/// # Examples
///
......@@ -750,7 +737,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
///
/// See also [`get_mut`], which is safe and does appropriate checks.
///
/// [`get_mut`]: struct.Rc.html#method.get_mut
/// [`get_mut`]: Rc::get_mut
///
/// # Safety
///
......@@ -796,7 +783,7 @@ pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
/// assert!(!Rc::ptr_eq(&five, &other_five));
/// ```
///
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
/// [`ptr::eq`]: core::ptr::eq
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.ptr.as_ptr() == other.ptr.as_ptr()
}
......@@ -814,9 +801,8 @@ impl<T: Clone> Rc<T> {
///
/// See also [`get_mut`], which will fail rather than cloning.
///
/// [`Weak`]: struct.Weak.html
/// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [`get_mut`]: struct.Rc.html#method.get_mut
/// [`clone`]: Clone::clone
/// [`get_mut`]: Rc::get_mut
///
/// # Examples
///
......@@ -1117,8 +1103,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
/// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!"
/// ```
///
/// [`Weak`]: ../../std/rc/struct.Weak.html
fn drop(&mut self) {
unsafe {
self.dec_strong();
......@@ -1600,11 +1584,7 @@ fn to_rc_slice(self) -> Rc<[T]> {
///
/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`].
///
/// [`Rc`]: struct.Rc.html
/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Option`]: ../../std/option/enum.Option.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`upgrade`]: Weak::upgrade
#[stable(feature = "rc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
// This is a `NonNull` to allow optimizing the size of this type in enums,
......@@ -1631,8 +1611,7 @@ impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`upgrade`]: #method.upgrade
/// [`None`]: ../../std/option/enum.Option.html
/// [`upgrade`]: Weak::upgrade
///
/// # Examples
///
......@@ -1671,7 +1650,7 @@ pub fn new() -> Weak<T> {
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
/// [`null`]: core::ptr::null
#[stable(feature = "rc_as_ptr", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
......@@ -1713,8 +1692,8 @@ pub fn as_ptr(&self) -> *const T {
/// assert_eq!(0, Rc::weak_count(&strong));
/// ```
///
/// [`from_raw`]: struct.Weak.html#method.from_raw
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
/// [`from_raw`]: Weak::from_raw
/// [`as_ptr`]: Weak::as_ptr
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn into_raw(self) -> *const T {
let result = self.as_ptr();
......@@ -1761,12 +1740,9 @@ pub fn into_raw(self) -> *const T {
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
/// ```
///
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Rc`]: struct.Rc.html
/// [`Weak`]: struct.Weak.html
/// [`new`]: struct.Weak.html#method.new
/// [`forget`]: ../../std/mem/fn.forget.html
/// [`into_raw`]: Weak::into_raw
/// [`upgrade`]: Weak::upgrade
/// [`new`]: Weak::new
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
......@@ -1794,9 +1770,6 @@ impl<T: ?Sized> Weak<T> {
///
/// Returns [`None`] if the inner value has since been dropped.
///
/// [`Rc`]: struct.Rc.html
/// [`None`]: ../../std/option/enum.Option.html
///
/// # Examples
///
/// ```
......@@ -1829,8 +1802,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
/// Gets the number of strong (`Rc`) pointers pointing to this allocation.
///
/// If `self` was created using [`Weak::new`], this will return 0.
///
/// [`Weak::new`]: #method.new
#[stable(feature = "weak_counts", since = "1.41.0")]
pub fn strong_count(&self) -> usize {
if let Some(inner) = self.inner() { inner.strong() } else { 0 }
......@@ -1899,7 +1870,7 @@ fn inner(&self) -> Option<&RcBox<T>> {
/// assert!(!first.ptr_eq(&third));
/// ```
///
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
/// [`ptr::eq`]: core::ptr::eq
#[inline]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
......@@ -1981,8 +1952,8 @@ impl<T> Default for Weak<T> {
/// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
/// it. Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`None`]: ../../std/option/enum.Option.html
/// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade
/// [`None`]: Option
/// [`upgrade`]: Weak::upgrade
///
/// # Examples
///
......
......@@ -70,11 +70,7 @@
//! * Further methods that return iterators are [`.split`], [`.splitn`],
//! [`.chunks`], [`.windows`] and more.
//!
//! [`Clone`]: ../../std/clone/trait.Clone.html
//! [`Eq`]: ../../std/cmp/trait.Eq.html
//! [`Ord`]: ../../std/cmp/trait.Ord.html
//! [`Iter`]: struct.Iter.html
//! [`Hash`]: ../../std/hash/trait.Hash.html
//! [`Hash`]: core::hash::Hash
//! [`.iter`]: ../../std/primitive.slice.html#method.iter
//! [`.iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
//! [`.split`]: ../../std/primitive.slice.html#method.split
......@@ -560,7 +556,7 @@ impl [u8] {
///
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
///
/// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
/// [`make_ascii_uppercase`]: u8::make_ascii_uppercase
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_uppercase(&self) -> Vec<u8> {
......@@ -577,7 +573,7 @@ pub fn to_ascii_uppercase(&self) -> Vec<u8> {
///
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
///
/// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
/// [`make_ascii_lowercase`]: u8::make_ascii_lowercase
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_lowercase(&self) -> Vec<u8> {
......
......@@ -2,9 +2,7 @@
//! Thread-safe reference-counting pointers.
//!
//! See the [`Arc<T>`][arc] documentation for more details.
//!
//! [arc]: struct.Arc.html
//! See the [`Arc<T>`][Arc] documentation for more details.
use core::any::Any;
use core::borrow;
......@@ -100,21 +98,21 @@
/// ## Breaking cycles with `Weak`
///
/// The [`downgrade`][downgrade] method can be used to create a non-owning
/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has
/// already been dropped. In other words, `Weak` pointers do not keep the value
/// inside the allocation alive; however, they *do* keep the allocation
/// (the backing store for the value) alive.
///
/// A cycle between `Arc` pointers will never be deallocated. For this reason,
/// [`Weak`][weak] is used to break cycles. For example, a tree could have
/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
/// [`Weak`] is used to break cycles. For example, a tree could have
/// strong `Arc` pointers from parent nodes to children, and [`Weak`]
/// pointers from children back to their parents.
///
/// # Cloning references
///
/// Creating a new reference from an existing reference counted pointer is done using the
/// `Clone` trait implemented for [`Arc<T>`][arc] and [`Weak<T>`][weak].
/// `Clone` trait implemented for [`Arc<T>`][Arc] and [`Weak<T>`][Weak].
///
/// ```
/// use std::sync::Arc;
......@@ -139,23 +137,20 @@
/// Arc::downgrade(&my_arc);
/// ```
///
/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the inner value may have
/// [`Weak<T>`][Weak] does not auto-dereference to `T`, because the inner value may have
/// already been dropped.
///
/// [arc]: struct.Arc.html
/// [weak]: struct.Weak.html
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [`Rc<T>`]: crate::rc::Rc
/// [clone]: Clone::clone
/// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html
/// [atomic]: ../../std/sync/atomic/index.html
/// [`Send`]: ../../std/marker/trait.Send.html
/// [`Sync`]: ../../std/marker/trait.Sync.html
/// [deref]: ../../std/ops/trait.Deref.html
/// [downgrade]: struct.Arc.html#method.downgrade
/// [upgrade]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
/// [atomic]: core::sync::atomic
/// [`Send`]: core::marker::Send
/// [`Sync`]: core::marker::Sync
/// [deref]: core::ops::Deref
/// [downgrade]: Arc::downgrade
/// [upgrade]: Weak::upgrade
/// [`RefCell<T>`]: core::cell::RefCell
/// [`std::sync`]: ../../std/sync/index.html
/// [`Arc::clone(&from)`]: #method.clone
///
......@@ -184,7 +179,7 @@
///
/// Sharing a mutable [`AtomicUsize`]:
///
/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize
///
/// ```no_run
/// use std::sync::Arc;
......@@ -254,11 +249,7 @@ unsafe fn from_ptr(ptr: *mut ArcInner<T>) -> Self {
///
/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
///
/// [`Arc`]: struct.Arc.html
/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Option`]: ../../std/option/enum.Option.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`upgrade`]: Weak::upgrade
#[stable(feature = "arc_weak", since = "1.4.0")]
pub struct Weak<T: ?Sized> {
// This is a `NonNull` to allow optimizing the size of this type in enums,
......@@ -396,13 +387,11 @@ pub fn pin(data: T) -> Pin<Arc<T>> {
/// Returns the inner value, if the `Arc` has exactly one strong reference.
///
/// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
/// Otherwise, an [`Err`] is returned with the same `Arc` that was
/// passed in.
///
/// This will succeed even if there are outstanding weak references.
///
/// [result]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// ```
......@@ -550,9 +539,7 @@ impl<T: ?Sized> Arc<T> {
/// Consumes the `Arc`, returning the wrapped pointer.
///
/// To avoid a memory leak the pointer must be converted back to an `Arc` using
/// [`Arc::from_raw`][from_raw].
///
/// [from_raw]: struct.Arc.html#method.from_raw
/// [`Arc::from_raw`].
///
/// # Examples
///
......@@ -612,8 +599,8 @@ pub fn as_ptr(this: &Self) -> *const T {
/// This function is unsafe because improper use may lead to memory unsafety,
/// even if the returned `Arc<T>` is never accessed.
///
/// [into_raw]: struct.Arc.html#method.into_raw
/// [transmute]: ../../std/mem/fn.transmute.html
/// [into_raw]: Arc::into_raw
/// [transmute]: core::mem::transmute
///
/// # Examples
///
......@@ -646,9 +633,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
}
}
/// Creates a new [`Weak`][weak] pointer to this allocation.
///
/// [weak]: struct.Weak.html
/// Creates a new [`Weak`] pointer to this allocation.
///
/// # Examples
///
......@@ -690,9 +675,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
}
}
/// Gets the number of [`Weak`][weak] pointers to this allocation.
///
/// [weak]: struct.Weak.html
/// Gets the number of [`Weak`] pointers to this allocation.
///
/// # Safety
///
......@@ -861,7 +844,7 @@ unsafe fn drop_slow(&mut self) {
/// assert!(!Arc::ptr_eq(&five, &other_five));
/// ```
///
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
/// [`ptr::eq`]: core::ptr::eq
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.ptr.as_ptr() == other.ptr.as_ptr()
}
......@@ -1098,7 +1081,7 @@ impl<T: ?Sized> Receiver for Arc<T> {}
impl<T: Clone> Arc<T> {
/// Makes a mutable reference into the given `Arc`.
///
/// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation,
/// If there are other `Arc` or [`Weak`] pointers to the same allocation,
/// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
/// to ensure unique ownership. This is also referred to as clone-on-write.
///
......@@ -1107,10 +1090,9 @@ impl<T: Clone> Arc<T> {
///
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
///
/// [weak]: struct.Weak.html
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [get_mut]: struct.Arc.html#method.get_mut
/// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut
/// [clone]: Clone::clone
/// [get_mut]: Arc::get_mut
/// [`Rc::make_mut`]: super::rc::Rc::make_mut
///
/// # Examples
///
......@@ -1184,18 +1166,16 @@ pub fn make_mut(this: &mut Self) -> &mut T {
impl<T: ?Sized> Arc<T> {
/// Returns a mutable reference into the given `Arc`, if there are
/// no other `Arc` or [`Weak`][weak] pointers to the same allocation.
/// no other `Arc` or [`Weak`] pointers to the same allocation.
///
/// Returns [`None`][option] otherwise, because it is not safe to
/// Returns [`None`] otherwise, because it is not safe to
/// mutate a shared value.
///
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
/// the inner value when there are other pointers.
///
/// [weak]: struct.Weak.html
/// [option]: ../../std/option/enum.Option.html
/// [make_mut]: struct.Arc.html#method.make_mut
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
/// [make_mut]: Arc::make_mut
/// [clone]: Clone::clone
///
/// # Examples
///
......@@ -1229,7 +1209,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
///
/// See also [`get_mut`], which is safe and does appropriate checks.
///
/// [`get_mut`]: struct.Arc.html#method.get_mut
/// [`get_mut`]: Arc::get_mut
///
/// # Safety
///
......@@ -1315,8 +1295,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
/// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!"
/// ```
///
/// [`Weak`]: ../../std/sync/struct.Weak.html
#[inline]
fn drop(&mut self) {
// Because `fetch_sub` is already atomic, we do not need to synchronize
......@@ -1401,8 +1379,7 @@ impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`] on the return value always gives [`None`].
///
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`upgrade`]: Weak::upgrade
///
/// # Examples
///
......@@ -1441,7 +1418,7 @@ pub fn new() -> Weak<T> {
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
/// [`null`]: core::ptr::null
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
......@@ -1483,8 +1460,8 @@ pub fn as_ptr(&self) -> *const T {
/// assert_eq!(0, Arc::weak_count(&strong));
/// ```
///
/// [`from_raw`]: struct.Weak.html#method.from_raw
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
/// [`from_raw`]: Weak::from_raw
/// [`as_ptr`]: Weak::as_ptr
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn into_raw(self) -> *const T {
let result = self.as_ptr();
......@@ -1530,12 +1507,10 @@ pub fn into_raw(self) -> *const T {
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
/// ```
///
/// [`new`]: struct.Weak.html#method.new
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Weak`]: struct.Weak.html
/// [`Arc`]: struct.Arc.html
/// [`forget`]: ../../std/mem/fn.forget.html
/// [`new`]: Weak::new
/// [`into_raw`]: Weak::into_raw
/// [`upgrade`]: Weak::upgrade
/// [`forget`]: std::mem::forget
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
......@@ -1565,9 +1540,6 @@ impl<T: ?Sized> Weak<T> {
///
/// Returns [`None`] if the inner value has since been dropped.
///
/// [`Arc`]: struct.Arc.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// # Examples
///
/// ```
......@@ -1619,8 +1591,6 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.
///
/// If `self` was created using [`Weak::new`], this will return 0.
///
/// [`Weak::new`]: #method.new
#[stable(feature = "weak_counts", since = "1.41.0")]
pub fn strong_count(&self) -> usize {
if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 }
......@@ -1637,8 +1607,6 @@ pub fn strong_count(&self) -> usize {
/// Due to implementation details, the returned value can be off by 1 in
/// either direction when other threads are manipulating any `Arc`s or
/// `Weak`s pointing to the same allocation.
///
/// [`Weak::new`]: #method.new
#[stable(feature = "weak_counts", since = "1.41.0")]
pub fn weak_count(&self) -> usize {
self.inner()
......@@ -1716,7 +1684,7 @@ fn inner(&self) -> Option<WeakInner<'_>> {
/// assert!(!first.ptr_eq(&third));
/// ```
///
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
/// [`ptr::eq`]: core::ptr::eq
#[inline]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
......@@ -1765,8 +1733,7 @@ impl<T> Default for Weak<T> {
/// Calling [`upgrade`] on the return value always
/// gives [`None`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade
/// [`upgrade`]: Weak::upgrade
///
/// # Examples
///
......
此差异已折叠。
......@@ -28,7 +28,6 @@
/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
......@@ -125,7 +124,6 @@ fn deref(&self) -> &T {
/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
......
......@@ -78,9 +78,9 @@
///
/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error.
///
/// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead.
/// If you'd like explicitly call the destructor of a value, [`mem::drop`] can be used instead.
///
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
/// [`mem::drop`]: drop
///
/// ## Drop order
///
......@@ -132,8 +132,6 @@
/// are `Copy` get implicitly duplicated by the compiler, making it very
/// hard to predict when, and how often destructors will be executed. As such,
/// these types cannot have destructors.
///
/// [`Copy`]: ../../std/marker/trait.Copy.html
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Drop {
......@@ -141,7 +139,7 @@ pub trait Drop {
///
/// This method is called implicitly when the value goes out of scope,
/// and cannot be called explicitly (this is compiler error [E0040]).
/// However, the [`std::mem::drop`] function in the prelude can be
/// However, the [`mem::drop`] function in the prelude can be
/// used to call the argument's `Drop` implementation.
///
/// When this method has been called, `self` has not yet been deallocated.
......@@ -156,12 +154,12 @@ pub trait Drop {
/// Note that even if this panics, the value is considered to be dropped;
/// you must not cause `drop` to be called again. This is normally automatically
/// handled by the compiler, but when using unsafe code, can sometimes occur
/// unintentionally, particularly when using [`std::ptr::drop_in_place`].
/// unintentionally, particularly when using [`ptr::drop_in_place`].
///
/// [E0040]: ../../error-index.html#E0040
/// [`panic!`]: ../macro.panic.html
/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
/// [`std::ptr::drop_in_place`]: ../../std/ptr/fn.drop_in_place.html
/// [`panic!`]: crate::panic!
/// [`mem::drop`]: drop
/// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
#[stable(feature = "rust1", since = "1.0.0")]
fn drop(&mut self);
}
......@@ -28,8 +28,6 @@
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/ch13-01-closures.html
/// [`FnMut`]: trait.FnMut.html
/// [`FnOnce`]: trait.FnOnce.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
......@@ -99,8 +97,6 @@ pub trait Fn<Args>: FnMut<Args> {
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/ch13-01-closures.html
/// [`Fn`]: trait.Fn.html
/// [`FnOnce`]: trait.FnOnce.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
......@@ -180,8 +176,6 @@ pub trait FnMut<Args>: FnOnce<Args> {
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
///
/// [book]: ../../book/ch13-01-closures.html
/// [`Fn`]: trait.Fn.html
/// [`FnMut`]: trait.FnMut.html
/// [function pointers]: ../../std/primitive.fn.html
/// [nomicon]: ../../nomicon/hrtb.html
///
......
......@@ -5,9 +5,6 @@
/// [`IndexMut`] is used instead. This allows nice things such as
/// `let value = v[index]` if the type of `value` implements [`Copy`].
///
/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html
/// [`Copy`]: ../../std/marker/trait.Copy.html
///
/// # Examples
///
/// The following example implements `Index` on a read-only `NucleotideCount`
......@@ -76,8 +73,6 @@ pub trait Index<Idx: ?Sized> {
/// an immutable value is requested, the [`Index`] trait is used instead. This
/// allows nice things such as `v[index] = value`.
///
/// [`Index`]: ../../std/ops/trait.Index.html
///
/// # Examples
///
/// A very simple implementation of a `Balance` struct that has two sides, where
......
......@@ -133,13 +133,7 @@
//! // `consume_and_return_x` can no longer be invoked at this point
//! ```
//!
//! [`Fn`]: trait.Fn.html
//! [`FnMut`]: trait.FnMut.html
//! [`FnOnce`]: trait.FnOnce.html
//! [`Add`]: trait.Add.html
//! [`Sub`]: trait.Sub.html
//! [`Mul`]: trait.Mul.html
//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`clone`]: Clone::clone
//! [operator precedence]: ../../reference/expressions.html#expression-precedence
#![stable(feature = "rust1", since = "1.0.0")]
......
......@@ -35,9 +35,7 @@
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
/// [slicing index]: crate::slice::SliceIndex
#[cfg_attr(not(bootstrap), lang = "RangeFull")]
#[doc(alias = "..")]
#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
......@@ -178,8 +176,6 @@ pub fn is_empty(&self) -> bool {
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`Iterator`]: ../iter/trait.IntoIterator.html
#[cfg_attr(not(bootstrap), lang = "RangeFrom")]
#[doc(alias = "..")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
......@@ -260,9 +256,7 @@ pub fn contains<U>(&self, item: &U) -> bool
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
/// [slicing index]: crate::slice::SliceIndex
#[cfg_attr(not(bootstrap), lang = "RangeTo")]
#[doc(alias = "..")]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
......@@ -315,8 +309,8 @@ pub fn contains<U>(&self, item: &U) -> bool
/// iteration has finished are **unspecified** other than that [`.is_empty()`]
/// will return `true` once no more values will be produced.
///
/// [fused]: ../iter/trait.FusedIterator.html
/// [`.is_empty()`]: #method.is_empty
/// [fused]: crate::iter::FusedIterator
/// [`.is_empty()`]: RangeInclusive::is_empty
///
/// # Examples
///
......@@ -383,8 +377,8 @@ pub const fn new(start: Idx, end: Idx) -> Self {
/// Note: the value returned by this method is unspecified after the range
/// has been iterated to exhaustion.
///
/// [`end()`]: #method.end
/// [`is_empty()`]: #method.is_empty
/// [`end()`]: RangeInclusive::end
/// [`is_empty()`]: RangeInclusive::is_empty
///
/// # Examples
///
......@@ -408,8 +402,8 @@ pub const fn start(&self) -> &Idx {
/// Note: the value returned by this method is unspecified after the range
/// has been iterated to exhaustion.
///
/// [`start()`]: #method.start
/// [`is_empty()`]: #method.is_empty
/// [`start()`]: RangeInclusive::start
/// [`is_empty()`]: RangeInclusive::is_empty
///
/// # Examples
///
......@@ -558,9 +552,7 @@ pub fn is_empty(&self) -> bool {
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// [slicing index]: ../slice/trait.SliceIndex.html
/// [slicing index]: crate::slice::SliceIndex
#[cfg_attr(not(bootstrap), lang = "RangeToInclusive")]
#[doc(alias = "..=")]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
......
......@@ -29,7 +29,7 @@
/// pointers. It is implemented automatically by the compiler.
///
/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
/// [unsize]: ../marker/trait.Unsize.html
/// [unsize]: crate::marker::Unsize
/// [nomicon-coerce]: ../../nomicon/coercions.html
#[unstable(feature = "coerce_unsized", issue = "27732")]
#[lang = "coerce_unsized"]
......
......@@ -12,7 +12,7 @@
//! # Examples
//!
//! [`Pattern`] is [implemented][pattern-impls] in the stable API for
//! [`&str`], [`char`], slices of [`char`], and functions and closures
//! [`&str`][`str`], [`char`], slices of [`char`], and functions and closures
//! implementing `FnMut(char) -> bool`.
//!
//! ```
......@@ -28,13 +28,6 @@
//! assert_eq!(s.find(|c: char| c.is_ascii_punctuation()), Some(35));
//! ```
//!
//! [`&str`]: ../../../std/primitive.str.html
//! [`char`]: ../../../std/primitive.char.html
//! [`str`]: ../../../std/primitive.str.html
//! [`DoubleEndedSearcher`]: trait.DoubleEndedSearcher.html
//! [`Pattern`]: trait.Pattern.html
//! [`ReverseSearcher`]: trait.ReverseSearcher.html
//! [`Searcher`]: trait.Searcher.html
//! [pattern-impls]: trait.Pattern.html#implementors
#![unstable(
......@@ -52,13 +45,13 @@
/// A string pattern.
///
/// A `Pattern<'a>` expresses that the implementing type
/// can be used as a string pattern for searching in a `&'a str`.
/// can be used as a string pattern for searching in a [`&'a str`][str].
///
/// For example, both `'a'` and `"aa"` are patterns that
/// would match at index `1` in the string `"baaaab"`.
///
/// The trait itself acts as a builder for an associated
/// `Searcher` type, which does the actual work of finding
/// [`Searcher`] type, which does the actual work of finding
/// occurrences of the pattern in a string.
///
/// Depending on the type of the pattern, the behaviour of methods like
......@@ -75,6 +68,7 @@
/// | `&String` | is substring |
///
/// # Examples
///
/// ```
/// // &str
/// assert_eq!("abaaa".find("ba"), Some(1));
......@@ -94,9 +88,6 @@
/// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4));
/// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None);
/// ```
///
/// [`str::find`]: ../../../std/primitive.str.html#method.find
/// [`str::contains`]: ../../../std/primitive.str.html#method.contains
pub trait Pattern<'a>: Sized {
/// Associated searcher for this pattern
type Searcher: Searcher<'a>;
......@@ -165,7 +156,7 @@ fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
// Searcher
/// Result of calling `Searcher::next()` or `ReverseSearcher::next_back()`.
/// Result of calling [`Searcher::next()`] or [`ReverseSearcher::next_back()`].
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SearchStep {
/// Expresses that a match of the pattern has been found at
......@@ -188,44 +179,47 @@ pub enum SearchStep {
/// matches of a pattern starting from the front (left) of a string.
///
/// It will be implemented by associated `Searcher`
/// types of the `Pattern` trait.
/// types of the [`Pattern`] trait.
///
/// The trait is marked unsafe because the indices returned by the
/// `next()` methods are required to lie on valid utf8 boundaries in
/// the haystack. This enables consumers of this trait to
/// [`next()`][Searcher::next] methods are required to lie on valid utf8
/// boundaries in the haystack. This enables consumers of this trait to
/// slice the haystack without additional runtime checks.
pub unsafe trait Searcher<'a> {
/// Getter for the underlying string to be searched in
///
/// Will always return the same `&str`
/// Will always return the same [`&str`][str].
fn haystack(&self) -> &'a str;
/// Performs the next search step starting from the front.
///
/// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
/// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
/// pattern, even partially.
/// - Returns `Done` if every byte of the haystack has been visited
/// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]` matches
/// the pattern.
/// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]` can
/// not match the pattern, even partially.
/// - Returns [`Done`][SearchStep::Done] if every byte of the haystack has
/// been visited.
///
/// The stream of `Match` and `Reject` values up to a `Done`
/// The stream of [`Match`][SearchStep::Match] and
/// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
/// will contain index ranges that are adjacent, non-overlapping,
/// covering the whole haystack, and laying on utf8 boundaries.
///
/// A `Match` result needs to contain the whole matched pattern,
/// however `Reject` results may be split up into arbitrary
/// many adjacent fragments. Both ranges may have zero length.
/// A [`Match`][SearchStep::Match] result needs to contain the whole matched
/// pattern, however [`Reject`][SearchStep::Reject] results may be split up
/// into arbitrary many adjacent fragments. Both ranges may have zero length.
///
/// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
/// might produce the stream
/// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]`
fn next(&mut self) -> SearchStep;
/// Finds the next `Match` result. See `next()`
/// Finds the next [`Match`][SearchStep::Match] result. See [`next()`][Searcher::next].
///
/// Unlike next(), there is no guarantee that the returned ranges
/// of this and next_reject will overlap. This will return (start_match, end_match),
/// where start_match is the index of where the match begins, and end_match is
/// the index after the end of the match.
/// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
/// of this and [`next_reject`][Searcher::next_reject] will overlap. This will return
/// `(start_match, end_match)`, where start_match is the index of where
/// the match begins, and end_match is the index after the end of the match.
#[inline]
fn next_match(&mut self) -> Option<(usize, usize)> {
loop {
......@@ -237,10 +231,11 @@ fn next_match(&mut self) -> Option<(usize, usize)> {
}
}
/// Finds the next `Reject` result. See `next()` and `next_match()`
/// Finds the next [`Reject`][SearchStep::Reject] result. See [`next()`][Searcher::next]
/// and [`next_match()`][Searcher::next_match].
///
/// Unlike next(), there is no guarantee that the returned ranges
/// of this and next_match will overlap.
/// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
/// of this and [`next_match`][Searcher::next_match] will overlap.
#[inline]
fn next_reject(&mut self) -> Option<(usize, usize)> {
loop {
......@@ -258,37 +253,41 @@ fn next_reject(&mut self) -> Option<(usize, usize)> {
/// This trait provides methods for searching for non-overlapping
/// matches of a pattern starting from the back (right) of a string.
///
/// It will be implemented by associated `Searcher`
/// types of the `Pattern` trait if the pattern supports searching
/// It will be implemented by associated [`Searcher`]
/// types of the [`Pattern`] trait if the pattern supports searching
/// for it from the back.
///
/// The index ranges returned by this trait are not required
/// to exactly match those of the forward search in reverse.
///
/// For the reason why this trait is marked unsafe, see them
/// parent trait `Searcher`.
/// parent trait [`Searcher`].
pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
/// Performs the next search step starting from the back.
///
/// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
/// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
/// pattern, even partially.
/// - Returns `Done` if every byte of the haystack has been visited
/// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]`
/// matches the pattern.
/// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]`
/// can not match the pattern, even partially.
/// - Returns [`Done`][SearchStep::Done] if every byte of the haystack
/// has been visited
///
/// The stream of `Match` and `Reject` values up to a `Done`
/// The stream of [`Match`][SearchStep::Match] and
/// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
/// will contain index ranges that are adjacent, non-overlapping,
/// covering the whole haystack, and laying on utf8 boundaries.
///
/// A `Match` result needs to contain the whole matched pattern,
/// however `Reject` results may be split up into arbitrary
/// many adjacent fragments. Both ranges may have zero length.
/// A [`Match`][SearchStep::Match] result needs to contain the whole matched
/// pattern, however [`Reject`][SearchStep::Reject] results may be split up
/// into arbitrary many adjacent fragments. Both ranges may have zero length.
///
/// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
/// might produce the stream
/// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`
/// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`.
fn next_back(&mut self) -> SearchStep;
/// Finds the next `Match` result. See `next_back()`
/// Finds the next [`Match`][SearchStep::Match] result.
/// See [`next_back()`][ReverseSearcher::next_back].
#[inline]
fn next_match_back(&mut self) -> Option<(usize, usize)> {
loop {
......@@ -300,7 +299,8 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
}
}
/// Finds the next `Reject` result. See `next_back()`
/// Finds the next [`Reject`][SearchStep::Reject] result.
/// See [`next_back()`][ReverseSearcher::next_back].
#[inline]
fn next_reject_back(&mut self) -> Option<(usize, usize)> {
loop {
......@@ -313,10 +313,10 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
}
}
/// A marker trait to express that a `ReverseSearcher`
/// can be used for a `DoubleEndedIterator` implementation.
/// A marker trait to express that a [`ReverseSearcher`]
/// can be used for a [`DoubleEndedIterator`] implementation.
///
/// For this, the impl of `Searcher` and `ReverseSearcher` need
/// For this, the impl of [`Searcher`] and [`ReverseSearcher`] need
/// to follow these conditions:
///
/// - All results of `next()` need to be identical
......@@ -328,7 +328,7 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
/// # Examples
///
/// `char::Searcher` is a `DoubleEndedSearcher` because searching for a
/// `char` only requires looking at one at a time, which behaves the same
/// [`char`] only requires looking at one at a time, which behaves the same
/// from both ends.
///
/// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
......@@ -355,13 +355,13 @@ pub struct CharSearcher<'a> {
/// `finger_back` is the current byte index of the reverse search.
/// Imagine that it exists after the byte at its index, i.e.
/// haystack[finger_back - 1] is the last byte of the slice we must inspect during
/// forward searching (and thus the first byte to be inspected when calling next_back())
/// forward searching (and thus the first byte to be inspected when calling next_back()).
finger_back: usize,
/// The character being searched for
needle: char,
// safety invariant: `utf8_size` must be less than 5
/// The number of bytes `needle` takes up when encoded in utf8
/// The number of bytes `needle` takes up when encoded in utf8.
utf8_size: usize,
/// A utf8 encoded copy of the `needle`
utf8_encoded: [u8; 4],
......@@ -521,7 +521,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
/// Searches for chars that are equal to a given `char`.
/// Searches for chars that are equal to a given [`char`].
///
/// # Examples
///
......@@ -772,7 +772,7 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> {
impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
/// Searches for chars that are equal to any of the chars in the slice.
/// Searches for chars that are equal to any of the [`char`]s in the slice.
///
/// # Examples
///
......@@ -821,7 +821,7 @@ unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F>
impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {}
/// Searches for chars that match the given predicate.
/// Searches for [`char`]s that match the given predicate.
///
/// # Examples
///
......
......@@ -467,3 +467,36 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
```
Another use case would be to run a test inside an emulator, or through a Virtual Machine.
### `--show-coverage`: get statistics about code documentation coverage
This option allows you to get a nice overview over your code documentation coverage, including both
doc-comments and code examples in the doc-comments. Example:
```bash
$ rustdoc src/lib.rs -Z unstable-options --show-coverage
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| lib.rs | 4 | 100.0% | 1 | 25.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 4 | 100.0% | 1 | 25.0% |
+-------------------------------------+------------+------------+------------+------------+
```
You can also use this option with the `--output-format` one:
```bash
$ rustdoc src/lib.rs -Z unstable-options --show-coverage --output-format json
{"lib.rs":{"total":4,"with_docs":4,"total_examples":4,"with_examples":1}}
```
Calculating code examples follows these rules:
1. These items aren't accounted by default:
* struct/union field
* enum variant
* constant
* static
* typedef
2. If one of the previously listed items has a code example, then it'll be counted.
......@@ -6,7 +6,7 @@ The tracking issue for this feature is: [#68793](https://github.com/rust-lang/ru
The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature.
CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete.
CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported [Windows platforms (Windows 8.1 onwards)](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete.
During compilation, the compiler identifies all indirect calls/jumps and adds CFG checks. It also emits metadata containing the relative addresses of all address-taken functions. At runtime, if the binary is run on a CFG-aware operating system, the loader uses the CFG metadata to generate a bitmap of the address space and marks those addresses that contain valid targets. On each indirect call, the inserted check determines whether the target address is marked in this bitmap. If the target is not valid, the process is terminated.
......@@ -19,8 +19,9 @@ CFG functionality is completely implemented in the LLVM backend and is supported
## When to use Control Flow Guard
The primary motivation for enabling CFG in Rust is to enhance security when linking against non-Rust code, especially C/C++ code. To achieve full CFG protection, all indirect calls (including any from Rust code) must have the appropriate CFG checks, as added by this flag. CFG can also improve security for Rust code that uses the `unsafe` keyword
The primary motivation for enabling CFG in Rust is to enhance security when linking against non-Rust code, especially C/C++ code. To achieve full CFG protection, all indirect calls (including any from Rust code) must have the appropriate CFG checks, as added by this flag. CFG can also improve security for Rust code that uses the `unsafe` keyword.
Another motivation behind CFG is to harden programs against [return-oriented programming (ROP)](https://en.wikipedia.org/wiki/Return-oriented_programming) attacks. CFG disallows an attacker from taking advantage of the program's own instructions while redirecting control flow in unexpected ways.
## Overhead of Control Flow Guard
......
......@@ -479,10 +479,13 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
_ => unreachable!(),
}
} else {
// We use i32 as the type for discarded outputs
's'
// We use i64x2 as the type for discarded outputs
'q'
};
format!("{{{}{}}}", class, idx)
} else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
// LLVM doesn't recognize x30
"lr".to_string()
} else {
format!("{{{}}}", reg.name())
}
......
#[cfg(test)]
mod tests {
use crate::*;
fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
let s = &format!("r{}", s);
let mut cursor = Cursor::new(s);
cursor.bump();
let (n_hashes, err) = cursor.raw_double_quoted_string(0);
assert_eq!(n_hashes, expected_hashes);
assert_eq!(err, expected_err);
}
#[test]
fn test_naked_raw_str() {
check_raw_str(r#""abc""#, 0, None);
}
#[test]
fn test_raw_no_start() {
check_raw_str(r##""abc"#"##, 0, None);
}
#[test]
fn test_too_many_terminators() {
// this error is handled in the parser later
check_raw_str(r###"#"abc"##"###, 1, None);
}
#[test]
fn test_unterminated() {
check_raw_str(
r#"#"abc"#,
1,
Some(RawStrError::NoTerminator {
expected: 1,
found: 0,
possible_terminator_offset: None,
}),
);
check_raw_str(
r###"##"abc"#"###,
2,
Some(RawStrError::NoTerminator {
expected: 2,
found: 1,
possible_terminator_offset: Some(7),
}),
);
// We're looking for "# not just any #
check_raw_str(
r###"##"abc#"###,
2,
Some(RawStrError::NoTerminator {
expected: 2,
found: 0,
possible_terminator_offset: None,
}),
)
}
#[test]
fn test_invalid_start() {
check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
}
#[test]
fn test_unterminated_no_pound() {
// https://github.com/rust-lang/rust/issues/70677
check_raw_str(
r#"""#,
0,
Some(RawStrError::NoTerminator {
expected: 0,
found: 0,
possible_terminator_offset: None,
}),
);
}
#[test]
fn test_valid_shebang() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#!/usr/bin/rustrun\nlet x = 5;";
assert_eq!(strip_shebang(input), Some(18));
}
#[test]
fn test_invalid_shebang_valid_rust_syntax() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#! [bad_attribute]";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_shebang_second_line() {
// Because shebangs are interpreted by the kernel, they must be on the first line
let input = "\n#!/bin/bash";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_shebang_space() {
let input = "#! /bin/bash";
assert_eq!(strip_shebang(input), Some(input.len()));
}
#[test]
fn test_shebang_empty_shebang() {
let input = "#! \n[attribute(foo)]";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_invalid_shebang_comment() {
let input = "#!//bin/ami/a/comment\n[";
assert_eq!(strip_shebang(input), None)
}
#[test]
fn test_invalid_shebang_another_comment() {
let input = "#!/*bin/ami/a/comment*/\n[attribute";
assert_eq!(strip_shebang(input), None)
}
#[test]
fn test_shebang_valid_rust_after() {
let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
assert_eq!(strip_shebang(input), Some(23))
}
#[test]
fn test_shebang_followed_by_attrib() {
let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
assert_eq!(strip_shebang(input), Some(19));
}
use super::*;
fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
let s = &format!("r{}", s);
let mut cursor = Cursor::new(s);
cursor.bump();
let (n_hashes, err) = cursor.raw_double_quoted_string(0);
assert_eq!(n_hashes, expected_hashes);
assert_eq!(err, expected_err);
}
#[test]
fn test_naked_raw_str() {
check_raw_str(r#""abc""#, 0, None);
}
#[test]
fn test_raw_no_start() {
check_raw_str(r##""abc"#"##, 0, None);
}
#[test]
fn test_too_many_terminators() {
// this error is handled in the parser later
check_raw_str(r###"#"abc"##"###, 1, None);
}
#[test]
fn test_unterminated() {
check_raw_str(
r#"#"abc"#,
1,
Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
);
check_raw_str(
r###"##"abc"#"###,
2,
Some(RawStrError::NoTerminator {
expected: 2,
found: 1,
possible_terminator_offset: Some(7),
}),
);
// We're looking for "# not just any #
check_raw_str(
r###"##"abc#"###,
2,
Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
)
}
#[test]
fn test_invalid_start() {
check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
}
#[test]
fn test_unterminated_no_pound() {
// https://github.com/rust-lang/rust/issues/70677
check_raw_str(
r#"""#,
0,
Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
);
}
#[test]
fn test_valid_shebang() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#!/usr/bin/rustrun\nlet x = 5;";
assert_eq!(strip_shebang(input), Some(18));
}
#[test]
fn test_invalid_shebang_valid_rust_syntax() {
// https://github.com/rust-lang/rust/issues/70528
let input = "#! [bad_attribute]";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_shebang_second_line() {
// Because shebangs are interpreted by the kernel, they must be on the first line
let input = "\n#!/bin/bash";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_shebang_space() {
let input = "#! /bin/bash";
assert_eq!(strip_shebang(input), Some(input.len()));
}
#[test]
fn test_shebang_empty_shebang() {
let input = "#! \n[attribute(foo)]";
assert_eq!(strip_shebang(input), None);
}
#[test]
fn test_invalid_shebang_comment() {
let input = "#!//bin/ami/a/comment\n[";
assert_eq!(strip_shebang(input), None)
}
#[test]
fn test_invalid_shebang_another_comment() {
let input = "#!/*bin/ami/a/comment*/\n[attribute";
assert_eq!(strip_shebang(input), None)
}
#[test]
fn test_shebang_valid_rust_after() {
let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
assert_eq!(strip_shebang(input), Some(23))
}
#[test]
fn test_shebang_followed_by_attrib() {
let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
assert_eq!(strip_shebang(input), Some(19));
}
......@@ -103,7 +103,7 @@ pub enum TerminatorKind<'tcx> {
unwind: Option<BasicBlock>,
},
/// Block ends with a call of a converging function.
/// Block ends with a call of a function.
Call {
/// The function that’s being called.
func: Operand<'tcx>,
......
use crate::astconv::AstConv;
use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
use std::collections::BTreeSet;
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
/// the type parameter's name as a placeholder.
pub(crate) fn complain_about_missing_type_params(
&self,
missing_type_params: Vec<String>,
def_id: DefId,
span: Span,
empty_generic_args: bool,
) {
if missing_type_params.is_empty() {
return;
}
let display =
missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
let mut err = struct_span_err!(
self.tcx().sess,
span,
E0393,
"the type parameter{} {} must be explicitly specified",
pluralize!(missing_type_params.len()),
display,
);
err.span_label(
self.tcx().def_span(def_id),
&format!(
"type parameter{} {} must be specified for this",
pluralize!(missing_type_params.len()),
display,
),
);
let mut suggested = false;
if let (Ok(snippet), true) = (
self.tcx().sess.source_map().span_to_snippet(span),
// Don't suggest setting the type params if there are some already: the order is
// tricky to get right and the user will already know what the syntax is.
empty_generic_args,
) {
if snippet.ends_with('>') {
// The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
// we would have to preserve the right order. For now, as clearly the user is
// aware of the syntax, we do nothing.
} else {
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
// least we can clue them to the correct syntax `Iterator<Type>`.
err.span_suggestion(
span,
&format!(
"set the type parameter{plural} to the desired type{plural}",
plural = pluralize!(missing_type_params.len()),
),
format!("{}<{}>", snippet, missing_type_params.join(", ")),
Applicability::HasPlaceholders,
);
suggested = true;
}
}
if !suggested {
err.span_label(
span,
format!(
"missing reference{} to {}",
pluralize!(missing_type_params.len()),
display,
),
);
}
err.note(
"because of the default `Self` reference, type parameters must be \
specified on object types",
);
err.emit();
}
/// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
/// an error and attempt to build a reasonable structured suggestion.
pub(crate) fn complain_about_internal_fn_trait(
&self,
span: Span,
trait_def_id: DefId,
trait_segment: &'a hir::PathSegment<'a>,
) {
let trait_def = self.tcx().trait_def(trait_def_id);
if !self.tcx().features().unboxed_closures
&& trait_segment.generic_args().parenthesized != trait_def.paren_sugar
{
let sess = &self.tcx().sess.parse_sess;
// For now, require that parenthetical notation be used only with `Fn()` etc.
let (msg, sugg) = if trait_def.paren_sugar {
(
"the precise format of `Fn`-family traits' type parameters is subject to \
change",
Some(format!(
"{}{} -> {}",
trait_segment.ident,
trait_segment
.args
.as_ref()
.and_then(|args| args.args.get(0))
.and_then(|arg| match arg {
hir::GenericArg::Type(ty) => match ty.kind {
hir::TyKind::Tup(t) => t
.iter()
.map(|e| sess.source_map().span_to_snippet(e.span))
.collect::<Result<Vec<_>, _>>()
.map(|a| a.join(", ")),
_ => sess.source_map().span_to_snippet(ty.span),
}
.map(|s| format!("({})", s))
.ok(),
_ => None,
})
.unwrap_or_else(|| "()".to_string()),
trait_segment
.generic_args()
.bindings
.iter()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
(true, hir::TypeBindingKind::Equality { ty }) => {
sess.source_map().span_to_snippet(ty.span).ok()
}
_ => None,
})
.unwrap_or_else(|| "()".to_string()),
)),
)
} else {
("parenthetical notation is only stable when used with `Fn`-family traits", None)
};
let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
if let Some(sugg) = sugg {
let msg = "use parenthetical notation instead";
err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
}
err.emit();
}
}
pub(crate) fn complain_about_assoc_type_not_found<I>(
&self,
all_candidates: impl Fn() -> I,
ty_param_name: &str,
assoc_name: Ident,
span: Span,
) where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
{
// The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
// valid span, so we point at the whole path segment instead.
let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
let mut err = struct_span_err!(
self.tcx().sess,
span,
E0220,
"associated type `{}` not found for `{}`",
assoc_name,
ty_param_name
);
let all_candidate_names: Vec<_> = all_candidates()
.map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
.flatten()
.filter_map(
|item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
)
.collect();
if let (Some(suggested_name), true) = (
find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
assoc_name.span != DUMMY_SP,
) {
err.span_suggestion(
assoc_name.span,
"there is an associated type with a similar name",
suggested_name.to_string(),
Applicability::MaybeIncorrect,
);
} else {
err.span_label(span, format!("associated type `{}` not found", assoc_name));
}
err.emit();
}
/// When there are any missing associated types, emit an E0191 error and attempt to supply a
/// reasonable suggestion on how to write it. For the case of multiple associated types in the
/// same trait bound have the same name (as they come from different super-traits), we instead
/// emit a generic note suggesting using a `where` clause to constraint instead.
pub(crate) fn complain_about_missing_associated_types(
&self,
associated_types: FxHashMap<Span, BTreeSet<DefId>>,
potential_assoc_types: Vec<Span>,
trait_bounds: &[hir::PolyTraitRef<'_>],
) {
if associated_types.values().all(|v| v.is_empty()) {
return;
}
let tcx = self.tcx();
// FIXME: Marked `mut` so that we can replace the spans further below with a more
// appropriate one, but this should be handled earlier in the span assignment.
let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
.into_iter()
.map(|(span, def_ids)| {
(span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
})
.collect();
let mut names = vec![];
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
// `issue-22560.rs`.
let mut trait_bound_spans: Vec<Span> = vec![];
for (span, items) in &associated_types {
if !items.is_empty() {
trait_bound_spans.push(*span);
}
for assoc_item in items {
let trait_def_id = assoc_item.container.id();
names.push(format!(
"`{}` (from trait `{}`)",
assoc_item.ident,
tcx.def_path_str(trait_def_id),
));
}
}
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
match &bound.trait_ref.path.segments[..] {
// FIXME: `trait_ref.path.span` can point to a full path with multiple
// segments, even though `trait_ref.path.segments` is of length `1`. Work
// around that bug here, even though it should be fixed elsewhere.
// This would otherwise cause an invalid suggestion. For an example, look at
// `src/test/ui/issues/issue-28344.rs` where instead of the following:
//
// error[E0191]: the value of the associated type `Output`
// (from trait `std::ops::BitXor`) must be specified
// --> $DIR/issue-28344.rs:4:17
// |
// LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
// | ^^^^^^ help: specify the associated type:
// | `BitXor<Output = Type>`
//
// we would output:
//
// error[E0191]: the value of the associated type `Output`
// (from trait `std::ops::BitXor`) must be specified
// --> $DIR/issue-28344.rs:4:17
// |
// LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
// | ^^^^^^^^^^^^^ help: specify the associated type:
// | `BitXor::bitor<Output = Type>`
[segment] if segment.args.is_none() => {
trait_bound_spans = vec![segment.ident.span];
associated_types = associated_types
.into_iter()
.map(|(_, items)| (segment.ident.span, items))
.collect();
}
_ => {}
}
}
names.sort();
trait_bound_spans.sort();
let mut err = struct_span_err!(
tcx.sess,
trait_bound_spans,
E0191,
"the value of the associated type{} {} must be specified",
pluralize!(names.len()),
names.join(", "),
);
let mut suggestions = vec![];
let mut types_count = 0;
let mut where_constraints = vec![];
for (span, assoc_items) in &associated_types {
let mut names: FxHashMap<_, usize> = FxHashMap::default();
for item in assoc_items {
types_count += 1;
*names.entry(item.ident.name).or_insert(0) += 1;
}
let mut dupes = false;
for item in assoc_items {
let prefix = if names[&item.ident.name] > 1 {
let trait_def_id = item.container.id();
dupes = true;
format!("{}::", tcx.def_path_str(trait_def_id))
} else {
String::new()
};
if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
err.span_label(sp, format!("`{}{}` defined here", prefix, item.ident));
}
}
if potential_assoc_types.len() == assoc_items.len() {
// Only suggest when the amount of missing associated types equals the number of
// extra type arguments present, as that gives us a relatively high confidence
// that the user forgot to give the associtated type's name. The canonical
// example would be trying to use `Iterator<isize>` instead of
// `Iterator<Item = isize>`.
for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
suggestions.push((*potential, format!("{} = {}", item.ident, snippet)));
}
}
} else if let (Ok(snippet), false) =
(tcx.sess.source_map().span_to_snippet(*span), dupes)
{
let types: Vec<_> =
assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect();
let code = if snippet.ends_with('>') {
// The user wrote `Trait<'a>` or similar and we don't have a type we can
// suggest, but at least we can clue them to the correct syntax
// `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
// suggestion.
format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
} else {
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
// least we can clue them to the correct syntax `Iterator<Item = Type>`.
format!("{}<{}>", snippet, types.join(", "))
};
suggestions.push((*span, code));
} else if dupes {
where_constraints.push(*span);
}
}
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
using the fully-qualified path to the associated types";
if !where_constraints.is_empty() && suggestions.is_empty() {
// If there are duplicates associated type names and a single trait bound do not
// use structured suggestion, it means that there are multiple super-traits with
// the same associated type name.
err.help(where_msg);
}
if suggestions.len() != 1 {
// We don't need this label if there's an inline suggestion, show otherwise.
for (span, assoc_items) in &associated_types {
let mut names: FxHashMap<_, usize> = FxHashMap::default();
for item in assoc_items {
types_count += 1;
*names.entry(item.ident.name).or_insert(0) += 1;
}
let mut label = vec![];
for item in assoc_items {
let postfix = if names[&item.ident.name] > 1 {
let trait_def_id = item.container.id();
format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
} else {
String::new()
};
label.push(format!("`{}`{}", item.ident, postfix));
}
if !label.is_empty() {
err.span_label(
*span,
format!(
"associated type{} {} must be specified",
pluralize!(label.len()),
label.join(", "),
),
);
}
}
}
if !suggestions.is_empty() {
err.multipart_suggestion(
&format!("specify the associated type{}", pluralize!(types_count)),
suggestions,
Applicability::HasPlaceholders,
);
if !where_constraints.is_empty() {
err.span_help(where_constraints, where_msg);
}
}
err.emit();
}
}
此差异已折叠。
//! Bounds are restrictions applied to some types after they've been converted into the
//! `ty` form from the HIR.
use rustc_hir::Constness;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_span::Span;
/// Collects together a list of type bounds. These lists of bounds occur in many places
/// in Rust's syntax:
///
/// ```text
/// trait Foo: Bar + Baz { }
/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter
///
/// fn foo<T: Bar + Baz>() { }
/// ^^^^^^^^^ bounding the type parameter `T`
///
/// impl dyn Bar + Baz
/// ^^^^^^^^^ bounding the forgotten dynamic type
/// ```
///
/// Our representation is a bit mixed here -- in some cases, we
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
/// A list of region bounds on the (implicit) self type. So if you
/// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
/// the `T` is not explicitly included).
pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
/// A list of trait bounds. So if you had `T: Debug` this would be
/// `T: Debug`. Note that the self-type is explicit here.
pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
/// A list of projection equality bounds. So if you had `T:
/// Iterator<Item = u32>` this would include `<T as
/// Iterator>::Item => u32`. Note that the self-type is explicit
/// here.
pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
/// `Some` if there is *no* `?Sized` predicate. The `span`
/// is the location in the source of the `T` declaration which can
/// be cited as the source of the `T: Sized` requirement.
pub implicitly_sized: Option<Span>,
}
impl<'tcx> Bounds<'tcx> {
/// Converts a bounds list into a flat set of predicates (like
/// where-clauses). Because some of our bounds listings (e.g.,
/// regions) don't include the self-type, you must supply the
/// self-type here (the `param_ty` parameter).
pub fn predicates(
&self,
tcx: TyCtxt<'tcx>,
param_ty: Ty<'tcx>,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
// If it could be sized, and is, add the `Sized` predicate.
let sized_predicate = self.implicitly_sized.and_then(|span| {
tcx.lang_items().sized_trait().map(|sized| {
let trait_ref = ty::Binder::bind(ty::TraitRef {
def_id: sized,
substs: tcx.mk_substs_trait(param_ty, &[]),
});
(trait_ref.without_const().to_predicate(tcx), span)
})
});
sized_predicate
.into_iter()
.chain(
self.region_bounds
.iter()
.map(|&(region_bound, span)| {
// Account for the binder being introduced below; no need to shift `param_ty`
// because, at present at least, it either only refers to early-bound regions,
// or it's a generic associated type that deliberately has escaping bound vars.
let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
(ty::Binder::bind(outlives).to_predicate(tcx), span)
})
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
(predicate, span)
}))
.chain(
self.projection_bounds
.iter()
.map(|&(projection, span)| (projection.to_predicate(tcx), span)),
),
)
.collect()
}
}
......@@ -14,7 +14,8 @@
//! At present, however, we do run collection across all items in the
//! crate as a kind of pass. This should eventually be factored away.
use crate::astconv::{AstConv, Bounds, SizedByDefault};
use crate::astconv::{AstConv, SizedByDefault};
use crate::bounds::Bounds;
use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::constrained_generic_params as cgp;
use crate::middle::resolve_lifetime as rl;
......
......@@ -79,6 +79,7 @@
pub mod expr_use_visitor;
mod astconv;
mod bounds;
mod check_unused;
mod coherence;
mod collect;
......@@ -109,7 +110,8 @@
use std::iter;
use astconv::{AstConv, Bounds};
use astconv::AstConv;
use bounds::Bounds;
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
......
......@@ -27,20 +27,29 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C
krate
}
#[derive(Default, Copy, Clone, Serialize)]
#[derive(Default, Copy, Clone, Serialize, Debug)]
struct ItemCount {
total: u64,
with_docs: u64,
total_examples: u64,
with_examples: u64,
}
impl ItemCount {
fn count_item(&mut self, has_docs: bool, has_doc_example: bool) {
fn count_item(
&mut self,
has_docs: bool,
has_doc_example: bool,
should_have_doc_examples: bool,
) {
self.total += 1;
if has_docs {
self.with_docs += 1;
}
if should_have_doc_examples || has_doc_example {
self.total_examples += 1;
}
if has_doc_example {
self.with_examples += 1;
}
......@@ -55,8 +64,8 @@ fn percentage(&self) -> Option<f64> {
}
fn examples_percentage(&self) -> Option<f64> {
if self.total > 0 {
Some((self.with_examples as f64 * 100.0) / self.total as f64)
if self.total_examples > 0 {
Some((self.with_examples as f64 * 100.0) / self.total_examples as f64)
} else {
None
}
......@@ -70,6 +79,7 @@ fn sub(self, rhs: Self) -> Self {
ItemCount {
total: self.total - rhs.total,
with_docs: self.with_docs - rhs.with_docs,
total_examples: self.total_examples - rhs.total_examples,
with_examples: self.with_examples - rhs.with_examples,
}
}
......@@ -79,6 +89,7 @@ impl ops::AddAssign for ItemCount {
fn add_assign(&mut self, rhs: Self) {
self.total += rhs.total;
self.with_docs += rhs.with_docs;
self.total_examples += rhs.total_examples;
self.with_examples += rhs.with_examples;
}
}
......@@ -121,7 +132,7 @@ fn print_results(&self, output_format: Option<OutputFormat>) {
let mut total = ItemCount::default();
fn print_table_line() {
println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
}
fn print_table_record(
......@@ -131,32 +142,25 @@ fn print_table_record(
examples_percentage: f64,
) {
println!(
"| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
name,
count.with_docs,
count.total,
percentage,
count.with_examples,
examples_percentage,
"| {:<35} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
name, count.with_docs, percentage, count.with_examples, examples_percentage,
);
}
print_table_line();
println!(
"| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |",
"File", "Documented", "Total", "Percentage", "Examples", "Percentage",
"| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} |",
"File", "Documented", "Percentage", "Examples", "Percentage",
);
print_table_line();
for (file, &count) in &self.items {
if let (Some(percentage), Some(examples_percentage)) =
(count.percentage(), count.examples_percentage())
{
if let Some(percentage) = count.percentage() {
print_table_record(
&limit_filename_len(file.to_string()),
count,
percentage,
examples_percentage,
count.examples_percentage().unwrap_or(0.),
);
total += count;
......@@ -176,19 +180,6 @@ fn print_table_record(
impl fold::DocFolder for CoverageCalculator {
fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
let has_docs = !i.attrs.doc_strings.is_empty();
let mut tests = Tests { found_tests: 0 };
find_testable_code(
&i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
&mut tests,
ErrorCodes::No,
false,
None,
);
let has_doc_example = tests.found_tests != 0;
match i.inner {
_ if !i.def_id.is_local() => {
// non-local items are skipped because they can be out of the users control,
......@@ -237,11 +228,37 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
}
}
_ => {
let has_docs = !i.attrs.doc_strings.is_empty();
let mut tests = Tests { found_tests: 0 };
let should_have_doc_examples = !matches!(i.inner,
clean::StructFieldItem(_)
| clean::VariantItem(_)
| clean::AssocConstItem(_, _)
| clean::AssocTypeItem(_, _)
| clean::TypedefItem(_, _)
| clean::StaticItem(_)
| clean::ConstantItem(_)
| clean::ExternCrateItem(_, _)
| clean::ImportItem(_)
| clean::PrimitiveItem(_)
| clean::KeywordItem(_)
);
find_testable_code(
&i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
&mut tests,
ErrorCodes::No,
false,
None,
);
let has_doc_example = tests.found_tests != 0;
debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename);
self.items
.entry(i.source.filename.clone())
.or_default()
.count_item(has_docs, has_doc_example);
self.items.entry(i.source.filename.clone()).or_default().count_item(
has_docs,
has_doc_example,
should_have_doc_examples,
);
}
}
......
......@@ -636,7 +636,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
}
match disambiguator.map(Disambiguator::ns) {
Some(ns @ ValueNS) => {
Some(ns @ (ValueNS | TypeNS)) => {
match self.resolve(
path_str,
disambiguator,
......@@ -660,28 +660,6 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
}
}
}
Some(ns @ TypeNS) => {
match self.resolve(
path_str,
disambiguator,
ns,
&current_item,
base_node,
&extra_fragment,
Some(&item),
) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link.
continue;
}
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
continue;
}
}
}
None => {
// Try everything!
let mut candidates = PerNS {
......
......@@ -553,3 +553,8 @@ pub unsafe fn $func(x: $ty) -> $ty {
// CHECK: fmov s0, s0
// CHECK: //NO_APP
check_reg!(v0_f64x2 f64x2 "s0" "fmov");
// Regression test for #75761
pub unsafe fn issue_75761() {
asm!("", out("v0") _, out("x30") _);
}
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 7 | 14 | 50.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 50.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 7 | 50.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
// check-pass
// compile-flags:-Z unstable-options --output-format json --show-coverage
// This check ensures that only one doc example is counted since they're "optional" on
// certain items.
/// ```
/// let x = 12;
/// ```
pub const Foo: u32 = 0;
/// doc
pub const Bar: u32 = 0;
{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}}
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...tdoc-ui/coverage/doc-examples.rs | 4 | 4 | 100.0% | 2 | 50.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 4 | 4 | 100.0% | 2 | 50.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 2 | 50.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 4 | 100.0% | 2 | 50.0% |
+-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 0 | 1 | 0.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 0.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 0 | 0.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 6 | 8 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 6 | 75.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% | 0 | 0.0% |
| <anon> | 2 | 2 | 100.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 3 | 3 | 100.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 100.0% | 0 | 0.0% |
| <anon> | 2 | 100.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 3 | 100.0% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
......@@ -12,16 +12,54 @@ pub enum Bar { A }
pub struct X;
/// Bar
///
/// ```
/// let x = 12;
/// ```
pub mod bar {
/// bar
pub struct Bar;
/// X
pub enum X { Y }
pub enum X {
/// ```
/// let x = "should be ignored!";
/// ```
Y
}
}
/// yolo
///
/// ```text
/// should not be counted as a code example!
/// ```
pub enum Yolo { X }
impl Yolo {
/// ```
/// let x = "should be ignored!";
/// ```
pub const Const: u32 = 0;
}
pub struct Xo<T: Clone> {
/// ```
/// let x = "should be ignored!";
/// ```
x: T,
}
/// ```
/// let x = "should be ignored!";
/// ```
pub static StaticFoo: u32 = 0;
/// ```
/// let x = "should be ignored!";
/// ```
pub const ConstFoo: u32 = 0;
/// ```
/// let x = "should be ignored!";
/// ```
pub type TypeFoo = u32;
{"$DIR/json.rs":{"total":13,"with_docs":7,"with_examples":0}}
{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}}
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 4 | 7 | 57.1% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...t/rustdoc-ui/coverage/private.rs | 4 | 57.1% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 4 | 57.1% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 6 | 7 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...oc-ui/coverage/statics-consts.rs | 6 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 6 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+------------+
| File | Documented | Total | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
| Total | 6 | 7 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+------------+
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 6 | 85.7% | 0 | 0.0% |
+-------------------------------------+------------+------------+------------+------------+
......@@ -9,7 +9,8 @@
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
// normalize-stderr-test "thread.*panicked.*\n" -> ""
// normalize-stderr-test "stack backtrace:\n" -> ""
// normalize-stderr-test " \d{1,}: .*\n" -> ""
// normalize-stderr-test "\s\d{1,}: .*\n" -> ""
// normalize-stderr-test "\s at .*\n" -> ""
// normalize-stderr-test ".*note: Some details.*\n" -> ""
#![allow(unconditional_panic)]
......
error: reaching this expression at runtime will panic or abort
--> $DIR/const-eval-query-stack.rs:18:28
--> $DIR/const-eval-query-stack.rs:19:28
|
LL | let x: &'static i32 = &(1 / 0);
| -^^^^^^^
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册