diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index fa5eb1823f1a0..87b86e590a4c8 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -36,8 +36,6 @@ extern "Rust" { /// /// 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 @@ pub struct Global; /// /// 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 /// /// ``` diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 5e304beff78ab..93d0df448ea14 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -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`]: struct.Box.html -//! [`Box::::from_raw(value)`]: struct.Box.html#method.from_raw -//! [`Box::::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`]: Box +//! [`Box::::from_raw(value)`]: Box::from_raw +//! [`Box::::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 @@ impl Box { /// Converts a `Box` 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) -> Box<[T]> { // *mut T and *mut [T; 1] have the same size and alignment @@ -386,9 +384,8 @@ impl Box { /// } /// ``` /// - /// [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 @@ impl Box { /// } /// ``` /// - /// [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) -> *mut T { @@ -478,8 +474,6 @@ impl Box { /// 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: diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 02a746f0e2488..5390b57a1d98d 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -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 { /// 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>>, @@ -80,11 +77,8 @@ impl Clone for Iter<'_, T> { /// 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 @@ impl fmt::Debug for IterMut<'_, T> { /// (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 { diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index a0b151a4496f1..a886e17f5a9c3 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -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 @@ use crate::string; /// 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(); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 2d25941a52412..892f794fc4232 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -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")] diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index e163a166b498f..2f744618d6936 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -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 @@ macro_rules! vec { /// 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 /// diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index d0a47ccea0a76..f8b1c21e9771c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -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 @@ impl Rc { /// 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 Rc { /// 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 @@ impl Rc { /// This function is unsafe because improper use may lead to memory unsafety, /// even if the returned `Rc` 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 @@ impl Rc { 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 @@ impl Rc { 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 @@ impl Rc { 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 @@ impl Rc { /// 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 @@ impl Rc { /// /// 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 @@ impl Rc { /// 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 Rc { /// /// 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 { /// 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 @@ impl> ToRcSlice for I { /// /// 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 { // This is a `NonNull` to allow optimizing the size of this type in enums, @@ -1631,8 +1611,7 @@ impl Weak { /// Constructs a new `Weak`, 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 @@ impl Weak { /// // 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 = NonNull::as_ptr(self.ptr); @@ -1713,8 +1692,8 @@ impl Weak { /// 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 @@ impl Weak { /// 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 Weak { /// /// 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 @@ impl Weak { /// 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 @@ impl Weak { /// 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 Default for Weak { /// Constructs a new `Weak`, 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 /// diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index b791c775548cd..8ea2c6dc859b2 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -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 { @@ -577,7 +573,7 @@ impl [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 { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b376330313758..4444a7a313298 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -2,9 +2,7 @@ //! Thread-safe reference-counting pointers. //! -//! See the [`Arc`][arc] documentation for more details. -//! -//! [arc]: struct.Arc.html +//! See the [`Arc`][Arc] documentation for more details. use core::any::Any; use core::borrow; @@ -100,21 +98,21 @@ macro_rules! acquire { /// ## 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`][arc] and [`Weak`][weak]. +/// `Clone` trait implemented for [`Arc`][Arc] and [`Weak`][Weak]. /// /// ``` /// use std::sync::Arc; @@ -139,23 +137,20 @@ macro_rules! acquire { /// Arc::downgrade(&my_arc); /// ``` /// -/// [`Weak`][weak] does not auto-dereference to `T`, because the inner value may have +/// [`Weak`][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`]: ../../std/rc/struct.Rc.html -/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone +/// [`Rc`]: 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`]: ../../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`]: core::cell::RefCell /// [`std::sync`]: ../../std/sync/index.html /// [`Arc::clone(&from)`]: #method.clone /// @@ -184,7 +179,7 @@ macro_rules! acquire { /// /// 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 @@ impl Arc { /// /// 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 { // This is a `NonNull` to allow optimizing the size of this type in enums, @@ -396,13 +387,11 @@ impl Arc { /// 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 Arc { /// 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 @@ impl Arc { /// This function is unsafe because improper use may lead to memory unsafety, /// even if the returned `Arc` 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 @@ impl Arc { } } - /// 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 @@ impl Arc { } } - /// 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 @@ impl Arc { /// 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 Receiver for Arc {} impl Arc { /// 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 Arc { /// /// 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 @@ impl Arc { impl Arc { /// 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 @@ impl Arc { /// /// 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 { /// 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 Weak { /// Constructs a new `Weak`, 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 @@ impl Weak { /// // 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 = NonNull::as_ptr(self.ptr); @@ -1483,8 +1460,8 @@ impl Weak { /// 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 @@ impl Weak { /// 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 Weak { /// /// 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 @@ impl Weak { /// 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 @@ impl Weak { /// 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 @@ impl Weak { /// 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 Default for Weak { /// 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 /// diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1399d0c020f16..9acf43931c6ba 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -57,6 +57,10 @@ use crate::marker::DiscriminantKind; use crate::mem; +// These imports are used for simplifying intra-doc links +#[cfg(doc)] +use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering}; + #[stable(feature = "drop_in_place", since = "1.8.0")] #[rustc_deprecated( reason = "no longer an intrinsic - use `ptr::drop_in_place` directly", @@ -71,710 +75,510 @@ extern "rust-intrinsic" { /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::Acquire`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_acq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_rel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_failacq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange`][compare_exchange]. - /// - /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange + /// [`atomic`] types via the `compare_exchange` method by passing + /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange`]. pub fn atomic_cxchg_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::SeqCst`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::Acquire`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_acq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::Release`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_rel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Acquire`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as both the `success` and `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::Relaxed`] as both the `success` and `failure` parameters. + /// For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::SeqCst`] as the `success` and [`Ordering::Acquire`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_failacq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::Acquire`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `success` and - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `failure` parameters. For example, - /// [`AtomicBool::compare_exchange_weak`][cew]. - /// - /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak + /// [`atomic`] types via the `compare_exchange_weak` method by passing + /// [`Ordering::AcqRel`] as the `success` and [`Ordering::Relaxed`] as the + /// `failure` parameters. For example, [`AtomicBool::compare_exchange_weak`]. pub fn atomic_cxchgweak_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Loads the current value of the pointer. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `load` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load). + /// [`atomic`] types via the `load` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`]. pub fn atomic_load(src: *const T) -> T; /// Loads the current value of the pointer. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `load` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load). + /// [`atomic`] types via the `load` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`]. pub fn atomic_load_acq(src: *const T) -> T; /// Loads the current value of the pointer. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `load` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load). + /// [`atomic`] types via the `load` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`]. pub fn atomic_load_relaxed(src: *const T) -> T; pub fn atomic_load_unordered(src: *const T) -> T; /// Stores the value at the specified memory location. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `store` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store). + /// [`atomic`] types via the `store` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`]. pub fn atomic_store(dst: *mut T, val: T); /// Stores the value at the specified memory location. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `store` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store). + /// [`atomic`] types via the `store` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`]. pub fn atomic_store_rel(dst: *mut T, val: T); /// Stores the value at the specified memory location. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `store` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store). + /// [`atomic`] types via the `store` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`]. pub fn atomic_store_relaxed(dst: *mut T, val: T); pub fn atomic_store_unordered(dst: *mut T, val: T); /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `swap` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). + /// [`atomic`] types via the `swap` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`]. pub fn atomic_xchg(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `swap` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). + /// [`atomic`] types via the `swap` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`]. pub fn atomic_xchg_acq(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `swap` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). + /// [`atomic`] types via the `swap` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`]. pub fn atomic_xchg_rel(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `swap` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). + /// [`atomic`] types via the `swap` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`]. pub fn atomic_xchg_acqrel(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `swap` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). + /// [`atomic`] types via the `swap` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`]. pub fn atomic_xchg_relaxed(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_add` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). + /// [`atomic`] types via the `fetch_add` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`]. pub fn atomic_xadd(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_add` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). + /// [`atomic`] types via the `fetch_add` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`]. pub fn atomic_xadd_acq(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_add` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). + /// [`atomic`] types via the `fetch_add` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`]. pub fn atomic_xadd_rel(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_add` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). + /// [`atomic`] types via the `fetch_add` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`]. pub fn atomic_xadd_acqrel(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_add` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). + /// [`atomic`] types via the `fetch_add` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`]. pub fn atomic_xadd_relaxed(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_sub` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). + /// [`atomic`] types via the `fetch_sub` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. pub fn atomic_xsub(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_sub` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). + /// [`atomic`] types via the `fetch_sub` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. pub fn atomic_xsub_acq(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_sub` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). + /// [`atomic`] types via the `fetch_sub` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. pub fn atomic_xsub_rel(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_sub` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). + /// [`atomic`] types via the `fetch_sub` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. pub fn atomic_xsub_acqrel(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_sub` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). + /// [`atomic`] types via the `fetch_sub` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`]. pub fn atomic_xsub_relaxed(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_and` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). + /// [`atomic`] types via the `fetch_and` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`]. pub fn atomic_and(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_and` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). + /// [`atomic`] types via the `fetch_and` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`]. pub fn atomic_and_acq(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_and` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). + /// [`atomic`] types via the `fetch_and` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`]. pub fn atomic_and_rel(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_and` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). + /// [`atomic`] types via the `fetch_and` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`]. pub fn atomic_and_acqrel(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_and` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). + /// [`atomic`] types via the `fetch_and` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`]. pub fn atomic_and_relaxed(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). + /// [`AtomicBool`] type via the `fetch_nand` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`]. pub fn atomic_nand(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). + /// [`AtomicBool`] type via the `fetch_nand` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`]. pub fn atomic_nand_acq(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). + /// [`AtomicBool`] type via the `fetch_nand` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`]. pub fn atomic_nand_rel(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). + /// [`AtomicBool`] type via the `fetch_nand` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`]. pub fn atomic_nand_acqrel(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). + /// [`AtomicBool`] type via the `fetch_nand` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`]. pub fn atomic_nand_relaxed(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_or` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). + /// [`atomic`] types via the `fetch_or` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`]. pub fn atomic_or(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_or` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). + /// [`atomic`] types via the `fetch_or` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`]. pub fn atomic_or_acq(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_or` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). + /// [`atomic`] types via the `fetch_or` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`]. pub fn atomic_or_rel(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_or` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). + /// [`atomic`] types via the `fetch_or` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`]. pub fn atomic_or_acqrel(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_or` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). + /// [`atomic`] types via the `fetch_or` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`]. pub fn atomic_or_relaxed(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_xor` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). + /// [`atomic`] types via the `fetch_xor` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`]. pub fn atomic_xor(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_xor` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). + /// [`atomic`] types via the `fetch_xor` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`]. pub fn atomic_xor_acq(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_xor` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). + /// [`atomic`] types via the `fetch_xor` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`]. pub fn atomic_xor_rel(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_xor` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). + /// [`atomic`] types via the `fetch_xor` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`]. pub fn atomic_xor_acqrel(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` types via the `fetch_xor` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) - /// as the `order`. For example, - /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). + /// [`atomic`] types via the `fetch_xor` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`]. pub fn atomic_xor_relaxed(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) - /// as the `order`. For example, - /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). + /// [`atomic`] signed integer types via the `fetch_max` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`]. pub fn atomic_max(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) - /// as the `order`. For example, - /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). + /// [`atomic`] signed integer types via the `fetch_max` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`]. pub fn atomic_max_acq(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) - /// as the `order`. For example, - /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). + /// [`atomic`] signed integer types via the `fetch_max` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`]. pub fn atomic_max_rel(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) - /// as the `order`. For example, - /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). + /// [`atomic`] signed integer types via the `fetch_max` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`]. pub fn atomic_max_acqrel(dst: *mut T, src: T) -> T; /// Maximum with the current value. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) - /// as the `order`. For example, - /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). + /// [`atomic`] signed integer types via the `fetch_max` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`]. pub fn atomic_max_relaxed(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) - /// as the `order`. For example, - /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). + /// [`atomic`] signed integer types via the `fetch_min` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`]. pub fn atomic_min(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) - /// as the `order`. For example, - /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). + /// [`atomic`] signed integer types via the `fetch_min` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`]. pub fn atomic_min_acq(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) - /// as the `order`. For example, - /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). + /// [`atomic`] signed integer types via the `fetch_min` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`]. pub fn atomic_min_rel(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) - /// as the `order`. For example, - /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). + /// [`atomic`] signed integer types via the `fetch_min` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`]. pub fn atomic_min_acqrel(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) - /// as the `order`. For example, - /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). + /// [`atomic`] signed integer types via the `fetch_min` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`]. pub fn atomic_min_relaxed(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) - /// as the `order`. For example, - /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). + /// [`atomic`] unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`]. pub fn atomic_umin(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) - /// as the `order`. For example, - /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). + /// [`atomic`] unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`]. pub fn atomic_umin_acq(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) - /// as the `order`. For example, - /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). + /// [`atomic`] unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`]. pub fn atomic_umin_rel(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) - /// as the `order`. For example, - /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). + /// [`atomic`] unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`]. pub fn atomic_umin_acqrel(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) - /// as the `order`. For example, - /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). + /// [`atomic`] unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`]. pub fn atomic_umin_relaxed(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) - /// as the `order`. For example, - /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). + /// [`atomic`] unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`]. pub fn atomic_umax(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) - /// as the `order`. For example, - /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). + /// [`atomic`] unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`]. pub fn atomic_umax_acq(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) - /// as the `order`. For example, - /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). + /// [`atomic`] unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`]. pub fn atomic_umax_rel(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) - /// as the `order`. For example, - /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). + /// [`atomic`] unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`]. pub fn atomic_umax_acqrel(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the - /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing - /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) - /// as the `order`. For example, - /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). + /// [`atomic`] unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`]. pub fn atomic_umax_relaxed(dst: *mut T, src: T) -> T; /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction @@ -823,33 +627,25 @@ extern "rust-intrinsic" { /// An atomic fence. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) - /// by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// [`atomic::fence`] by passing [`Ordering::SeqCst`] /// as the `order`. pub fn atomic_fence(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) - /// by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// [`atomic::fence`] by passing [`Ordering::Acquire`] /// as the `order`. pub fn atomic_fence_acq(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) - /// by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// [`atomic::fence`] by passing [`Ordering::Release`] /// as the `order`. pub fn atomic_fence_rel(); /// An atomic fence. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) - /// by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// [`atomic::fence`] by passing [`Ordering::AcqRel`] /// as the `order`. pub fn atomic_fence_acqrel(); @@ -861,9 +657,7 @@ extern "rust-intrinsic" { /// such as when interacting with signal handlers. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) - /// by passing - /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`] /// as the `order`. pub fn atomic_singlethreadfence(); /// A compiler-only memory barrier. @@ -874,9 +668,7 @@ extern "rust-intrinsic" { /// such as when interacting with signal handlers. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) - /// by passing - /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`] /// as the `order`. pub fn atomic_singlethreadfence_acq(); /// A compiler-only memory barrier. @@ -887,9 +679,7 @@ extern "rust-intrinsic" { /// such as when interacting with signal handlers. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) - /// by passing - /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// [`atomic::compiler_fence`] by passing [`Ordering::Release`] /// as the `order`. pub fn atomic_singlethreadfence_rel(); /// A compiler-only memory barrier. @@ -900,9 +690,7 @@ extern "rust-intrinsic" { /// such as when interacting with signal handlers. /// /// The stabilized version of this intrinsic is available in - /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) - /// by passing - /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`] /// as the `order`. pub fn atomic_singlethreadfence_acqrel(); @@ -930,8 +718,7 @@ extern "rust-intrinsic" { /// macro, which panics when it is executed, it is *undefined behavior* to /// reach code marked with this function. /// - /// The stabilized version of this intrinsic is - /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html). + /// The stabilized version of this intrinsic is [`crate::hint::unreachable_unchecked`]. #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")] pub fn unreachable() -> !; @@ -975,8 +762,7 @@ extern "rust-intrinsic" { /// More specifically, this is the offset in bytes between successive /// items of the same type, including alignment padding. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::size_of`](../../std/mem/fn.size_of.html). + /// The stabilized version of this intrinsic is [`size_of`]. #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")] pub fn size_of() -> usize; @@ -984,14 +770,12 @@ extern "rust-intrinsic" { /// /// Drop glue is not run on the destination. /// - /// The stabilized version of this intrinsic is - /// [`std::ptr::write`](../../std/ptr/fn.write.html). + /// The stabilized version of this intrinsic is [`crate::ptr::write`]. pub fn move_val_init(dst: *mut T, src: T); /// The minimum alignment of a type. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::align_of`](../../std/mem/fn.align_of.html). + /// The stabilized version of this intrinsic is [`crate::mem::align_of`]. #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of() -> usize; /// The preferred alignment of a type. @@ -1002,21 +786,18 @@ extern "rust-intrinsic" { /// The size of the referenced value in bytes. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). + /// The stabilized version of this intrinsic is [`size_of_val`]. #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] pub fn size_of_val(_: *const T) -> usize; /// The required alignment of the referenced value. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::align_of_val`](../../std/mem/fn.align_of_val.html). + /// The stabilized version of this intrinsic is [`crate::mem::align_of_val`]. #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] pub fn min_align_of_val(_: *const T) -> usize; /// Gets a static string slice containing the name of a type. /// - /// The stabilized version of this intrinsic is - /// [`std::any::type_name`](../../std/any/fn.type_name.html) + /// The stabilized version of this intrinsic is [`crate::any::type_name`]. #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub fn type_name() -> &'static str; @@ -1024,8 +805,7 @@ extern "rust-intrinsic" { /// function will return the same value for a type regardless of whichever /// crate it is invoked in. /// - /// The stabilized version of this intrinsic is - /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) + /// The stabilized version of this intrinsic is [`crate::any::TypeId::of`]. #[rustc_const_stable(feature = "const_type_id", since = "1.46.0")] pub fn type_id() -> u64; @@ -1049,15 +829,14 @@ extern "rust-intrinsic" { /// Gets a reference to a static `Location` indicating where it was called. /// - /// Consider using [`std::panic::Location::caller`](../../std/panic/struct.Location.html#method.caller) - /// instead. + /// Consider using [`crate::panic::Location::caller`] instead. #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] pub fn caller_location() -> &'static crate::panic::Location<'static>; /// Moves a value out of scope without running drop glue. /// - /// This exists solely for [`mem::forget_unsized`](../../std/mem/fn.forget_unsized.html); - /// normal `forget` uses `ManuallyDrop` instead. + /// This exists solely for [`mem::forget_unsized`]; normal `forget` uses + /// `ManuallyDrop` instead. pub fn forget(_: T); /// Reinterprets the bits of a value of one type as another type. @@ -1300,8 +1079,7 @@ extern "rust-intrinsic" { /// If the actual type neither requires drop glue nor implements /// `Copy`, then the return value of this function is unspecified. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html). + /// The stabilized version of this intrinsic is [`needs_drop`]. #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")] pub fn needs_drop() -> bool; @@ -1371,13 +1149,11 @@ extern "rust-intrinsic" { /// Performs a volatile load from the `src` pointer. /// - /// The stabilized version of this intrinsic is - /// [`std::ptr::read_volatile`](../../std/ptr/fn.read_volatile.html). + /// The stabilized version of this intrinsic is [`crate::ptr::read_volatile`]. pub fn volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// - /// The stabilized version of this intrinsic is - /// [`std::ptr::write_volatile`](../../std/ptr/fn.write_volatile.html). + /// The stabilized version of this intrinsic is [`crate::ptr::write_volatile`]. pub fn volatile_store(dst: *mut T, val: T); /// Performs a volatile load from the `src` pointer @@ -1526,22 +1302,22 @@ extern "rust-intrinsic" { /// Returns the minimum of two `f32` values. /// /// The stabilized version of this intrinsic is - /// [`std::f32::min`](../../std/primitive.f32.html#method.min) + /// [`f32::min`] pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. /// /// The stabilized version of this intrinsic is - /// [`std::f64::min`](../../std/primitive.f64.html#method.min) + /// [`f64::min`] pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. /// /// The stabilized version of this intrinsic is - /// [`std::f32::max`](../../std/primitive.f32.html#method.max) + /// [`f32::max`] pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. /// /// The stabilized version of this intrinsic is - /// [`std::f64::max`](../../std/primitive.f64.html#method.max) + /// [`f64::max`] pub fn maxnumf64(x: f64, y: f64) -> f64; /// Copies the sign from `y` to `x` for `f32` values. @@ -1648,15 +1424,14 @@ extern "rust-intrinsic" { /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range /// () /// - /// Stabilized as [`f32::to_int_unchecked`](../../std/primitive.f32.html#method.to_int_unchecked) - /// and [`f64::to_int_unchecked`](../../std/primitive.f64.html#method.to_int_unchecked). + /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. pub fn float_to_int_unchecked(value: Float) -> Int; /// Returns the number of bits set in an integer type `T` /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, - /// [`std::u32::count_ones`](../../std/primitive.u32.html#method.count_ones) + /// [`u32::count_ones`] #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] pub fn ctpop(x: T) -> T; @@ -1664,7 +1439,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `leading_zeros` method. For example, - /// [`std::u32::leading_zeros`](../../std/primitive.u32.html#method.leading_zeros) + /// [`u32::leading_zeros`] /// /// # Examples /// @@ -1715,7 +1490,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `trailing_zeros` method. For example, - /// [`std::u32::trailing_zeros`](../../std/primitive.u32.html#method.trailing_zeros) + /// [`u32::trailing_zeros`] /// /// # Examples /// @@ -1766,7 +1541,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, - /// [`std::u32::swap_bytes`](../../std/primitive.u32.html#method.swap_bytes) + /// [`u32::swap_bytes`] #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")] pub fn bswap(x: T) -> T; @@ -1774,7 +1549,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, - /// [`std::u32::reverse_bits`](../../std/primitive.u32.html#method.reverse_bits) + /// [`u32::reverse_bits`] #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")] pub fn bitreverse(x: T) -> T; @@ -1782,7 +1557,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, - /// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add) + /// [`u32::overflowing_add`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] pub fn add_with_overflow(x: T, y: T) -> (T, bool); @@ -1790,7 +1565,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, - /// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub) + /// [`u32::overflowing_sub`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] pub fn sub_with_overflow(x: T, y: T) -> (T, bool); @@ -1798,7 +1573,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, - /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul) + /// [`u32::overflowing_mul`] #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")] pub fn mul_with_overflow(x: T, y: T) -> (T, bool); @@ -1813,7 +1588,7 @@ extern "rust-intrinsic" { /// /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, - /// [`std::u32::checked_div`](../../std/primitive.u32.html#method.checked_div) + /// [`u32::checked_div`] #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_div(x: T, y: T) -> T; /// Returns the remainder of an unchecked division, resulting in @@ -1821,7 +1596,7 @@ extern "rust-intrinsic" { /// /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_rem` method. For example, - /// [`std::u32::checked_rem`](../../std/primitive.u32.html#method.checked_rem) + /// [`u32::checked_rem`] #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_rem(x: T, y: T) -> T; @@ -1830,7 +1605,7 @@ extern "rust-intrinsic" { /// /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, - /// [`std::u32::checked_shl`](../../std/primitive.u32.html#method.checked_shl) + /// [`u32::checked_shl`] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shl(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when @@ -1838,7 +1613,7 @@ extern "rust-intrinsic" { /// /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, - /// [`std::u32::checked_shr`](../../std/primitive.u32.html#method.checked_shr) + /// [`u32::checked_shr`] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shr(x: T, y: T) -> T; @@ -1867,7 +1642,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, - /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left) + /// [`u32::rotate_left`] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] pub fn rotate_left(x: T, y: T) -> T; @@ -1875,7 +1650,7 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, - /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right) + /// [`u32::rotate_right`] #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")] pub fn rotate_right(x: T, y: T) -> T; @@ -1883,21 +1658,21 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `checked_add` method. For example, - /// [`std::u32::checked_add`](../../std/primitive.u32.html#method.checked_add) + /// [`u32::checked_add`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `checked_sub` method. For example, - /// [`std::u32::checked_sub`](../../std/primitive.u32.html#method.checked_sub) + /// [`u32::checked_sub`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `checked_mul` method. For example, - /// [`std::u32::checked_mul`](../../std/primitive.u32.html#method.checked_mul) + /// [`u32::checked_mul`] #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_mul(a: T, b: T) -> T; @@ -1905,30 +1680,28 @@ extern "rust-intrinsic" { /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, - /// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add) + /// [`u32::saturating_add`] #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")] pub fn saturating_add(a: T, b: T) -> T; /// Computes `a - b`, while saturating at numeric bounds. /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, - /// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub) + /// [`u32::saturating_sub`] #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")] pub fn saturating_sub(a: T, b: T) -> T; /// Returns the value of the discriminant for the variant in 'v', /// cast to a `u64`; if `T` has no discriminant, returns 0. /// - /// The stabilized version of this intrinsic is - /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html) + /// The stabilized version of this intrinsic is [`crate::mem::discriminant`]. #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] pub fn discriminant_value(v: &T) -> ::Discriminant; /// Returns the number of variants of the type `T` cast to a `usize`; /// if `T` has no variants, returns 0. Uninhabited variants will be counted. /// - /// The to-be-stabilized version of this intrinsic is - /// [`std::mem::variant_count`](../../std/mem/fn.variant_count.html) + /// The to-be-stabilized version of this intrinsic is [`variant_count`]. #[rustc_const_unstable(feature = "variant_count", issue = "73662")] pub fn variant_count() -> usize; @@ -1989,7 +1762,6 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but /// with the argument order swapped. /// -/// [`copy`]: ./fn.copy.html /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy /// /// # Safety @@ -2014,10 +1786,9 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - /// Note that even if the effectively copied size (`count * size_of::()`) is /// `0`, the pointers must be non-NULL and properly aligned. /// -/// [`Copy`]: ../marker/trait.Copy.html -/// [`read`]: ../ptr/fn.read.html -/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value -/// [valid]: ../ptr/index.html#safety +/// [`read`]: crate::ptr::read +/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value +/// [valid]: crate::ptr#safety /// /// # Examples /// @@ -2096,7 +1867,6 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { /// order swapped. Copying takes place as if the bytes were copied from `src` /// to a temporary array and then copied from the array to `dst`. /// -/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove /// /// # Safety @@ -2117,10 +1887,9 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { /// Note that even if the effectively copied size (`count * size_of::()`) is /// `0`, the pointers must be non-NULL and properly aligned. /// -/// [`Copy`]: ../marker/trait.Copy.html -/// [`read`]: ../ptr/fn.read.html -/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value -/// [valid]: ../ptr/index.html#safety +/// [`read`]: crate::ptr::read +/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value +/// [valid]: crate::ptr#safety /// /// # Examples /// @@ -2178,7 +1947,7 @@ pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { /// Note that even if the effectively copied size (`count * size_of::()`) is /// `0`, the pointer must be non-NULL and properly aligned. /// -/// [valid]: ../ptr/index.html#safety +/// [valid]: crate::ptr#safety /// /// # Examples /// diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 3faeb170b0637..d6c097eee17bf 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -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 @@ impl Deref for &mut 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 diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 06cfc36363615..ce7d1c3d06ddc 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -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); } diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 3e5cad2b185a1..bfdec43f7d80b 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -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: FnMut { /// 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: FnOnce { /// 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 /// diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index 763b33606fe88..3c2ada5761233 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -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 { /// 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 diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index e3e5934b44be1..c19bd6e441e69 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -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")] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index e9ab82b539849..ccabd66aaf6eb 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -35,9 +35,7 @@ use crate::hash::Hash; /// 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 @@ impl> Range { /// 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 @@ impl> RangeFrom { /// 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 @@ impl> RangeTo { /// 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 @@ impl RangeInclusive { /// 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 @@ impl RangeInclusive { /// 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 @@ impl> RangeInclusive { /// 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)] diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index 95a4393592be9..483362023b22c 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -29,7 +29,7 @@ use crate::marker::Unsize; /// 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"] diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 14f1f293d40d6..1cc2de5b8756a 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -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 @@ use crate::slice::memchr; /// 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 @@ use crate::slice::memchr; /// | `&String` | is substring | /// /// # Examples +/// /// ``` /// // &str /// assert_eq!("abaaa".find("ba"), Some(1)); @@ -94,9 +88,6 @@ use crate::slice::memchr; /// 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 @@ pub trait Pattern<'a>: Sized { // 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 @@ pub unsafe trait Searcher<'a> { } } - /// 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 @@ pub unsafe trait Searcher<'a> { /// 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 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { } } - /// 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 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { } } -/// 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 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { /// # 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 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { 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 @@ where 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 /// diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index d16c2a9d0342c..f45e229506438 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -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. diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md index 4115825e92083..c43d91bf070ed 100644 --- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md @@ -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 diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index a6062de6bf8af..4fef94dde5f7a 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -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()) } diff --git a/src/librustc_lexer/src/tests.rs b/src/librustc_lexer/src/tests.rs index e6acc26ec2f34..b0209ac2899d6 100644 --- a/src/librustc_lexer/src/tests.rs +++ b/src/librustc_lexer/src/tests.rs @@ -1,137 +1,122 @@ -#[cfg(test)] -mod tests { - use crate::*; - - fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option) { - 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) { + 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)); } diff --git a/src/librustc_middle/mir/terminator/mod.rs b/src/librustc_middle/mir/terminator/mod.rs index e8fe3a97a10c7..fcfd648c2b7aa 100644 --- a/src/librustc_middle/mir/terminator/mod.rs +++ b/src/librustc_middle/mir/terminator/mod.rs @@ -103,7 +103,7 @@ pub enum TerminatorKind<'tcx> { unwind: Option, }, - /// 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>, diff --git a/src/librustc_typeck/astconv/errors.rs b/src/librustc_typeck/astconv/errors.rs new file mode 100644 index 0000000000000..685243f54cb90 --- /dev/null +++ b/src/librustc_typeck/astconv/errors.rs @@ -0,0 +1,388 @@ +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, + 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::>().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`. + 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::, _>>() + .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( + &self, + all_candidates: impl Fn() -> I, + ty_param_name: &str, + assoc_name: Ident, + span: Span, + ) where + I: Iterator>, + { + // 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>, + potential_assoc_types: Vec, + 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> = 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 = 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` + // + // 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` + [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` instead of + // `Iterator`. + 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`. + 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(); + } +} diff --git a/src/librustc_typeck/astconv/generics.rs b/src/librustc_typeck/astconv/generics.rs new file mode 100644 index 0000000000000..84dab6de95819 --- /dev/null +++ b/src/librustc_typeck/astconv/generics.rs @@ -0,0 +1,596 @@ +use crate::astconv::{ + AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, +}; +use rustc_ast::ast::ParamKindOrd; +use rustc_errors::{pluralize, struct_span_err, DiagnosticId, ErrorReported}; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_hir::{GenericArg, GenericArgs}; +use rustc_middle::ty::{ + self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt, +}; +use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session}; +use rustc_span::{symbol::kw, MultiSpan, Span}; + +use smallvec::SmallVec; + +impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + /// Report an error that a generic argument did not match the generic parameter that was + /// expected. + fn generic_arg_mismatch_err( + sess: &Session, + arg: &GenericArg<'_>, + kind: &'static str, + help: Option<&str>, + ) { + let mut err = struct_span_err!( + sess, + arg.span(), + E0747, + "{} provided when a {} was expected", + arg.descr(), + kind, + ); + + let unordered = sess.features_untracked().const_generics; + let kind_ord = match kind { + "lifetime" => ParamKindOrd::Lifetime, + "type" => ParamKindOrd::Type, + "constant" => ParamKindOrd::Const { unordered }, + // It's more concise to match on the string representation, though it means + // the match is non-exhaustive. + _ => bug!("invalid generic parameter kind {}", kind), + }; + let arg_ord = match arg { + GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, + GenericArg::Type(_) => ParamKindOrd::Type, + GenericArg::Const(_) => ParamKindOrd::Const { unordered }, + }; + + // This note is only true when generic parameters are strictly ordered by their kind. + if kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { + let (first, last) = + if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; + err.note(&format!("{} arguments must be provided before {} arguments", first, last)); + if let Some(help) = help { + err.help(help); + } + } + + err.emit(); + } + + /// Creates the relevant generic argument substitutions + /// corresponding to a set of generic parameters. This is a + /// rather complex function. Let us try to explain the role + /// of each of its parameters: + /// + /// To start, we are given the `def_id` of the thing we are + /// creating the substitutions for, and a partial set of + /// substitutions `parent_substs`. In general, the substitutions + /// for an item begin with substitutions for all the "parents" of + /// that item -- e.g., for a method it might include the + /// parameters from the impl. + /// + /// Therefore, the method begins by walking down these parents, + /// starting with the outermost parent and proceed inwards until + /// it reaches `def_id`. For each parent `P`, it will check `parent_substs` + /// first to see if the parent's substitutions are listed in there. If so, + /// we can append those and move on. Otherwise, it invokes the + /// three callback functions: + /// + /// - `args_for_def_id`: given the `DefId` `P`, supplies back the + /// generic arguments that were given to that parent from within + /// the path; so e.g., if you have `::Bar`, the `DefId` + /// might refer to the trait `Foo`, and the arguments might be + /// `[T]`. The boolean value indicates whether to infer values + /// for arguments whose values were not explicitly provided. + /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, + /// instantiate a `GenericArg`. + /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then + /// creates a suitable inference variable. + pub fn create_substs_for_generic_args<'b>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + parent_substs: &[subst::GenericArg<'tcx>], + has_self: bool, + self_ty: Option>, + arg_count: GenericArgCountResult, + args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), + mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, + mut inferred_kind: impl FnMut( + Option<&[subst::GenericArg<'tcx>]>, + &GenericParamDef, + bool, + ) -> subst::GenericArg<'tcx>, + ) -> SubstsRef<'tcx> { + // Collect the segments of the path; we need to substitute arguments + // for parameters throughout the entire path (wherever there are + // generic parameters). + let mut parent_defs = tcx.generics_of(def_id); + let count = parent_defs.count(); + let mut stack = vec![(def_id, parent_defs)]; + while let Some(def_id) = parent_defs.parent { + parent_defs = tcx.generics_of(def_id); + stack.push((def_id, parent_defs)); + } + + // We manually build up the substitution, rather than using convenience + // methods in `subst.rs`, so that we can iterate over the arguments and + // parameters in lock-step linearly, instead of trying to match each pair. + let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); + // Iterate over each segment of the path. + while let Some((def_id, defs)) = stack.pop() { + let mut params = defs.params.iter().peekable(); + + // If we have already computed substitutions for parents, we can use those directly. + while let Some(¶m) = params.peek() { + if let Some(&kind) = parent_substs.get(param.index as usize) { + substs.push(kind); + params.next(); + } else { + break; + } + } + + // `Self` is handled first, unless it's been handled in `parent_substs`. + if has_self { + if let Some(¶m) = params.peek() { + if param.index == 0 { + if let GenericParamDefKind::Type { .. } = param.kind { + substs.push( + self_ty + .map(|ty| ty.into()) + .unwrap_or_else(|| inferred_kind(None, param, true)), + ); + params.next(); + } + } + } + } + + // Check whether this segment takes generic arguments and the user has provided any. + let (generic_args, infer_args) = args_for_def_id(def_id); + + let mut args = + generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable(); + + // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. + // If we later encounter a lifetime, we know that the arguments were provided in the + // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be + // inferred, so we can use it for diagnostics later. + let mut force_infer_lt = None; + + loop { + // We're going to iterate through the generic arguments that the user + // provided, matching them with the generic parameters we expect. + // Mismatches can occur as a result of elided lifetimes, or for malformed + // input. We try to handle both sensibly. + match (args.peek(), params.peek()) { + (Some(&arg), Some(¶m)) => { + match (arg, ¶m.kind, arg_count.explicit_late_bound) { + (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) + | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) + | (GenericArg::Const(_), GenericParamDefKind::Const, _) => { + substs.push(provided_kind(param, arg)); + args.next(); + params.next(); + } + ( + GenericArg::Type(_) | GenericArg::Const(_), + GenericParamDefKind::Lifetime, + _, + ) => { + // We expected a lifetime argument, but got a type or const + // argument. That means we're inferring the lifetimes. + substs.push(inferred_kind(None, param, infer_args)); + force_infer_lt = Some(arg); + params.next(); + } + (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => { + // We've come across a lifetime when we expected something else in + // the presence of explicit late bounds. This is most likely + // due to the presence of the explicit bound so we're just going to + // ignore it. + args.next(); + } + (_, kind, _) => { + // We expected one kind of parameter, but the user provided + // another. This is an error. However, if we already know that + // the arguments don't match up with the parameters, we won't issue + // an additional error, as the user already knows what's wrong. + if arg_count.correct.is_ok() + && arg_count.explicit_late_bound == ExplicitLateBound::No + { + // We're going to iterate over the parameters to sort them out, and + // show that order to the user as a possible order for the parameters + let mut param_types_present = defs + .params + .clone() + .into_iter() + .map(|param| { + ( + match param.kind { + GenericParamDefKind::Lifetime => { + ParamKindOrd::Lifetime + } + GenericParamDefKind::Type { .. } => { + ParamKindOrd::Type + } + GenericParamDefKind::Const => { + ParamKindOrd::Const { + unordered: tcx + .sess + .features_untracked() + .const_generics, + } + } + }, + param, + ) + }) + .collect::>(); + param_types_present.sort_by_key(|(ord, _)| *ord); + let (mut param_types_present, ordered_params): ( + Vec, + Vec, + ) = param_types_present.into_iter().unzip(); + param_types_present.dedup(); + + Self::generic_arg_mismatch_err( + tcx.sess, + arg, + kind.descr(), + Some(&format!( + "reorder the arguments: {}: `<{}>`", + param_types_present + .into_iter() + .map(|ord| format!("{}s", ord.to_string())) + .collect::>() + .join(", then "), + ordered_params + .into_iter() + .filter_map(|param| { + if param.name == kw::SelfUpper { + None + } else { + Some(param.name.to_string()) + } + }) + .collect::>() + .join(", ") + )), + ); + } + + // We've reported the error, but we want to make sure that this + // problem doesn't bubble down and create additional, irrelevant + // errors. In this case, we're simply going to ignore the argument + // and any following arguments. The rest of the parameters will be + // inferred. + while args.next().is_some() {} + } + } + } + + (Some(&arg), None) => { + // We should never be able to reach this point with well-formed input. + // There are three situations in which we can encounter this issue. + // + // 1. The number of arguments is incorrect. In this case, an error + // will already have been emitted, and we can ignore it. + // 2. There are late-bound lifetime parameters present, yet the + // lifetime arguments have also been explicitly specified by the + // user. + // 3. We've inferred some lifetimes, which have been provided later (i.e. + // after a type or const). We want to throw an error in this case. + + if arg_count.correct.is_ok() + && arg_count.explicit_late_bound == ExplicitLateBound::No + { + let kind = arg.descr(); + assert_eq!(kind, "lifetime"); + let provided = + force_infer_lt.expect("lifetimes ought to have been inferred"); + Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None); + } + + break; + } + + (None, Some(¶m)) => { + // If there are fewer arguments than parameters, it means + // we're inferring the remaining arguments. + substs.push(inferred_kind(Some(&substs), param, infer_args)); + params.next(); + } + + (None, None) => break, + } + } + } + + tcx.intern_substs(&substs) + } + + /// Checks that the correct number of generic arguments have been provided. + /// Used specifically for function calls. + pub fn check_generic_arg_count_for_call( + tcx: TyCtxt<'_>, + span: Span, + def: &ty::Generics, + seg: &hir::PathSegment<'_>, + is_method_call: bool, + ) -> GenericArgCountResult { + let empty_args = hir::GenericArgs::none(); + let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def); + Self::check_generic_arg_count( + tcx, + span, + def, + if let Some(ref args) = seg.args { args } else { &empty_args }, + if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value }, + def.parent.is_none() && def.has_self, // `has_self` + seg.infer_args || suppress_mismatch, // `infer_args` + ) + } + + /// Checks that the correct number of generic arguments have been provided. + /// This is used both for datatypes and function calls. + pub(crate) fn check_generic_arg_count( + tcx: TyCtxt<'_>, + span: Span, + def: &ty::Generics, + args: &hir::GenericArgs<'_>, + position: GenericArgPosition, + has_self: bool, + infer_args: bool, + ) -> GenericArgCountResult { + // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. + // that lifetimes will proceed types. So it suffices to check the number of each generic + // arguments in order to validate them with respect to the generic parameters. + let param_counts = def.own_counts(); + let arg_counts = args.own_counts(); + let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; + + let mut defaults: ty::GenericParamCount = Default::default(); + for param in &def.params { + match param.kind { + GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Type { has_default, .. } => { + defaults.types += has_default as usize + } + GenericParamDefKind::Const => { + // FIXME(const_generics:defaults) + } + }; + } + + if position != GenericArgPosition::Type && !args.bindings.is_empty() { + Self::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); + } + + let explicit_late_bound = + Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position); + + let check_kind_count = |kind, + required, + permitted, + provided, + offset, + unexpected_spans: &mut Vec, + silent| { + debug!( + "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}", + kind, required, permitted, provided, offset + ); + // We enforce the following: `required` <= `provided` <= `permitted`. + // For kinds without defaults (e.g.., lifetimes), `required == permitted`. + // For other kinds (i.e., types), `permitted` may be greater than `required`. + if required <= provided && provided <= permitted { + return Ok(()); + } + + if silent { + return Err(true); + } + + // Unfortunately lifetime and type parameter mismatches are typically styled + // differently in diagnostics, which means we have a few cases to consider here. + let (bound, quantifier) = if required != permitted { + if provided < required { + (required, "at least ") + } else { + // provided > permitted + (permitted, "at most ") + } + } else { + (required, "") + }; + + let (spans, label) = if required == permitted && provided > permitted { + // In the case when the user has provided too many arguments, + // we want to point to the unexpected arguments. + let spans: Vec = args.args[offset + permitted..offset + provided] + .iter() + .map(|arg| arg.span()) + .collect(); + unexpected_spans.extend(spans.clone()); + (spans, format!("unexpected {} argument", kind)) + } else { + ( + vec![span], + format!( + "expected {}{} {} argument{}", + quantifier, + bound, + kind, + pluralize!(bound), + ), + ) + }; + + let mut err = tcx.sess.struct_span_err_with_code( + spans.clone(), + &format!( + "wrong number of {} arguments: expected {}{}, found {}", + kind, quantifier, bound, provided, + ), + DiagnosticId::Error("E0107".into()), + ); + for span in spans { + err.span_label(span, label.as_str()); + } + err.emit(); + + Err(true) + }; + + let mut arg_count_correct = Ok(()); + let mut unexpected_spans = vec![]; + + if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { + arg_count_correct = check_kind_count( + "lifetime", + param_counts.lifetimes, + param_counts.lifetimes, + arg_counts.lifetimes, + 0, + &mut unexpected_spans, + explicit_late_bound == ExplicitLateBound::Yes, + ) + .and(arg_count_correct); + } + // FIXME(const_generics:defaults) + if !infer_args || arg_counts.consts > param_counts.consts { + arg_count_correct = check_kind_count( + "const", + param_counts.consts, + param_counts.consts, + arg_counts.consts, + arg_counts.lifetimes + arg_counts.types, + &mut unexpected_spans, + false, + ) + .and(arg_count_correct); + } + // Note that type errors are currently be emitted *after* const errors. + if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize + { + arg_count_correct = check_kind_count( + "type", + param_counts.types - defaults.types - has_self as usize, + param_counts.types - has_self as usize, + arg_counts.types, + arg_counts.lifetimes, + &mut unexpected_spans, + false, + ) + .and(arg_count_correct); + } + + GenericArgCountResult { + explicit_late_bound, + correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch { + reported: if reported_err { Some(ErrorReported) } else { None }, + invalid_args: unexpected_spans, + }), + } + } + + /// Report error if there is an explicit type parameter when using `impl Trait`. + pub(crate) fn check_impl_trait( + tcx: TyCtxt<'_>, + seg: &hir::PathSegment<'_>, + generics: &ty::Generics, + ) -> bool { + let explicit = !seg.infer_args; + let impl_trait = generics.params.iter().any(|param| match param.kind { + ty::GenericParamDefKind::Type { + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), + .. + } => true, + _ => false, + }); + + if explicit && impl_trait { + let spans = seg + .generic_args() + .args + .iter() + .filter_map(|arg| match arg { + GenericArg::Type(_) => Some(arg.span()), + _ => None, + }) + .collect::>(); + + let mut err = struct_span_err! { + tcx.sess, + spans.clone(), + E0632, + "cannot provide explicit generic arguments when `impl Trait` is \ + used in argument position" + }; + + for span in spans { + err.span_label(span, "explicit generic argument not allowed"); + } + + err.emit(); + } + + impl_trait + } + + /// Emits an error regarding forbidden type binding associations + pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { + let mut err = struct_span_err!( + tcx.sess, + span, + E0229, + "associated type bindings are not allowed here" + ); + err.span_label(span, "associated type not allowed here").emit(); + } + + /// Prohibits explicit lifetime arguments if late-bound lifetime parameters + /// are present. This is used both for datatypes and function calls. + pub(crate) fn prohibit_explicit_late_bound_lifetimes( + tcx: TyCtxt<'_>, + def: &ty::Generics, + args: &hir::GenericArgs<'_>, + position: GenericArgPosition, + ) -> ExplicitLateBound { + let param_counts = def.own_counts(); + let arg_counts = args.own_counts(); + let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; + + if infer_lifetimes { + ExplicitLateBound::No + } else if let Some(span_late) = def.has_late_bound_regions { + let msg = "cannot specify lifetime arguments explicitly \ + if late bound lifetime parameters are present"; + let note = "the late bound lifetime parameter is introduced here"; + let span = args.args[0].span(); + if position == GenericArgPosition::Value + && arg_counts.lifetimes != param_counts.lifetimes + { + let mut err = tcx.sess.struct_span_err(span, msg); + err.span_note(span_late, note); + err.emit(); + } else { + let mut multispan = MultiSpan::from_span(span); + multispan.push_span_label(span_late, note.to_string()); + tcx.struct_span_lint_hir( + LATE_BOUND_LIFETIME_ARGUMENTS, + args.args[0].id(), + multispan, + |lint| lint.build(msg).emit(), + ); + } + ExplicitLateBound::Yes + } else { + ExplicitLateBound::No + } + } +} diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv/mod.rs similarity index 65% rename from src/librustc_typeck/astconv.rs rename to src/librustc_typeck/astconv/mod.rs index 86081b150710d..15c19afdb4a20 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv/mod.rs @@ -1,17 +1,17 @@ -// ignore-tidy-filelength FIXME(#67418) Split up this file. //! Conversion from AST representation of types to the `ty.rs` representation. //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. -// ignore-tidy-filelength +mod errors; +mod generics; +use crate::bounds::Bounds; use crate::collect::PlaceholderHirTyCollector; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; -use rustc_ast::{util::lev_distance::find_best_match_for_name, ParamKindOrd}; +use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::ErrorReported; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError}; +use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -19,15 +19,11 @@ use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::lang_items::SizedTraitLangItem; use rustc_hir::{Constness, GenericArg, GenericArgs}; use rustc_middle::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{ - self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; -use rustc_middle::ty::{GenericParamDef, GenericParamDefKind}; -use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; -use rustc_session::parse::feature_err; -use rustc_session::Session; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_middle::ty::GenericParamDefKind; +use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; +use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; @@ -138,8 +134,10 @@ pub enum ExplicitLateBound { No, } +/// Denotes the "position" of a generic argument, indicating if it is a generic type, +/// generic function or generic method call. #[derive(Copy, Clone, PartialEq)] -enum GenericArgPosition { +pub(crate) enum GenericArgPosition { Type, Value, // e.g., functions MethodCall, @@ -243,533 +241,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { substs } - /// Report error if there is an explicit type parameter when using `impl Trait`. - fn check_impl_trait( - tcx: TyCtxt<'_>, - seg: &hir::PathSegment<'_>, - generics: &ty::Generics, - ) -> bool { - let explicit = !seg.infer_args; - let impl_trait = generics.params.iter().any(|param| match param.kind { - ty::GenericParamDefKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - .. - } => true, - _ => false, - }); - - if explicit && impl_trait { - let spans = seg - .generic_args() - .args - .iter() - .filter_map(|arg| match arg { - GenericArg::Type(_) => Some(arg.span()), - _ => None, - }) - .collect::>(); - - let mut err = struct_span_err! { - tcx.sess, - spans.clone(), - E0632, - "cannot provide explicit generic arguments when `impl Trait` is \ - used in argument position" - }; - - for span in spans { - err.span_label(span, "explicit generic argument not allowed"); - } - - err.emit(); - } - - impl_trait - } - - /// Checks that the correct number of generic arguments have been provided. - /// Used specifically for function calls. - pub fn check_generic_arg_count_for_call( - tcx: TyCtxt<'_>, - span: Span, - def: &ty::Generics, - seg: &hir::PathSegment<'_>, - is_method_call: bool, - ) -> GenericArgCountResult { - let empty_args = hir::GenericArgs::none(); - let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def); - Self::check_generic_arg_count( - tcx, - span, - def, - if let Some(ref args) = seg.args { args } else { &empty_args }, - if is_method_call { GenericArgPosition::MethodCall } else { GenericArgPosition::Value }, - def.parent.is_none() && def.has_self, // `has_self` - seg.infer_args || suppress_mismatch, // `infer_args` - ) - } - - /// Checks that the correct number of generic arguments have been provided. - /// This is used both for datatypes and function calls. - fn check_generic_arg_count( - tcx: TyCtxt<'_>, - span: Span, - def: &ty::Generics, - args: &hir::GenericArgs<'_>, - position: GenericArgPosition, - has_self: bool, - infer_args: bool, - ) -> GenericArgCountResult { - // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. - // that lifetimes will proceed types. So it suffices to check the number of each generic - // arguments in order to validate them with respect to the generic parameters. - let param_counts = def.own_counts(); - let arg_counts = args.own_counts(); - let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; - - let mut defaults: ty::GenericParamCount = Default::default(); - for param in &def.params { - match param.kind { - GenericParamDefKind::Lifetime => {} - GenericParamDefKind::Type { has_default, .. } => { - defaults.types += has_default as usize - } - GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) - } - }; - } - - if position != GenericArgPosition::Type && !args.bindings.is_empty() { - AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); - } - - let explicit_late_bound = - Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position); - - let check_kind_count = |kind, - required, - permitted, - provided, - offset, - unexpected_spans: &mut Vec, - silent| { - debug!( - "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}", - kind, required, permitted, provided, offset - ); - // We enforce the following: `required` <= `provided` <= `permitted`. - // For kinds without defaults (e.g.., lifetimes), `required == permitted`. - // For other kinds (i.e., types), `permitted` may be greater than `required`. - if required <= provided && provided <= permitted { - return Ok(()); - } - - if silent { - return Err(true); - } - - // Unfortunately lifetime and type parameter mismatches are typically styled - // differently in diagnostics, which means we have a few cases to consider here. - let (bound, quantifier) = if required != permitted { - if provided < required { - (required, "at least ") - } else { - // provided > permitted - (permitted, "at most ") - } - } else { - (required, "") - }; - - let (spans, label) = if required == permitted && provided > permitted { - // In the case when the user has provided too many arguments, - // we want to point to the unexpected arguments. - let spans: Vec = args.args[offset + permitted..offset + provided] - .iter() - .map(|arg| arg.span()) - .collect(); - unexpected_spans.extend(spans.clone()); - (spans, format!("unexpected {} argument", kind)) - } else { - ( - vec![span], - format!( - "expected {}{} {} argument{}", - quantifier, - bound, - kind, - pluralize!(bound), - ), - ) - }; - - let mut err = tcx.sess.struct_span_err_with_code( - spans.clone(), - &format!( - "wrong number of {} arguments: expected {}{}, found {}", - kind, quantifier, bound, provided, - ), - DiagnosticId::Error("E0107".into()), - ); - for span in spans { - err.span_label(span, label.as_str()); - } - err.emit(); - - Err(true) - }; - - let mut arg_count_correct = Ok(()); - let mut unexpected_spans = vec![]; - - if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { - arg_count_correct = check_kind_count( - "lifetime", - param_counts.lifetimes, - param_counts.lifetimes, - arg_counts.lifetimes, - 0, - &mut unexpected_spans, - explicit_late_bound == ExplicitLateBound::Yes, - ) - .and(arg_count_correct); - } - // FIXME(const_generics:defaults) - if !infer_args || arg_counts.consts > param_counts.consts { - arg_count_correct = check_kind_count( - "const", - param_counts.consts, - param_counts.consts, - arg_counts.consts, - arg_counts.lifetimes + arg_counts.types, - &mut unexpected_spans, - false, - ) - .and(arg_count_correct); - } - // Note that type errors are currently be emitted *after* const errors. - if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize - { - arg_count_correct = check_kind_count( - "type", - param_counts.types - defaults.types - has_self as usize, - param_counts.types - has_self as usize, - arg_counts.types, - arg_counts.lifetimes, - &mut unexpected_spans, - false, - ) - .and(arg_count_correct); - } - - GenericArgCountResult { - explicit_late_bound, - correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch { - reported: if reported_err { Some(ErrorReported) } else { None }, - invalid_args: unexpected_spans, - }), - } - } - - /// Report an error that a generic argument did not match the generic parameter that was - /// expected. - fn generic_arg_mismatch_err( - sess: &Session, - arg: &GenericArg<'_>, - kind: &'static str, - help: Option<&str>, - ) { - let mut err = struct_span_err!( - sess, - arg.span(), - E0747, - "{} provided when a {} was expected", - arg.descr(), - kind, - ); - - let unordered = sess.features_untracked().const_generics; - let kind_ord = match kind { - "lifetime" => ParamKindOrd::Lifetime, - "type" => ParamKindOrd::Type, - "constant" => ParamKindOrd::Const { unordered }, - // It's more concise to match on the string representation, though it means - // the match is non-exhaustive. - _ => bug!("invalid generic parameter kind {}", kind), - }; - let arg_ord = match arg { - GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, - GenericArg::Type(_) => ParamKindOrd::Type, - GenericArg::Const(_) => ParamKindOrd::Const { unordered }, - }; - - // This note is only true when generic parameters are strictly ordered by their kind. - if kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { - let (first, last) = - if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; - err.note(&format!("{} arguments must be provided before {} arguments", first, last)); - if let Some(help) = help { - err.help(help); - } - } - - err.emit(); - } - - /// Creates the relevant generic argument substitutions - /// corresponding to a set of generic parameters. This is a - /// rather complex function. Let us try to explain the role - /// of each of its parameters: - /// - /// To start, we are given the `def_id` of the thing we are - /// creating the substitutions for, and a partial set of - /// substitutions `parent_substs`. In general, the substitutions - /// for an item begin with substitutions for all the "parents" of - /// that item -- e.g., for a method it might include the - /// parameters from the impl. - /// - /// Therefore, the method begins by walking down these parents, - /// starting with the outermost parent and proceed inwards until - /// it reaches `def_id`. For each parent `P`, it will check `parent_substs` - /// first to see if the parent's substitutions are listed in there. If so, - /// we can append those and move on. Otherwise, it invokes the - /// three callback functions: - /// - /// - `args_for_def_id`: given the `DefId` `P`, supplies back the - /// generic arguments that were given to that parent from within - /// the path; so e.g., if you have `::Bar`, the `DefId` - /// might refer to the trait `Foo`, and the arguments might be - /// `[T]`. The boolean value indicates whether to infer values - /// for arguments whose values were not explicitly provided. - /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, - /// instantiate a `GenericArg`. - /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then - /// creates a suitable inference variable. - pub fn create_substs_for_generic_args<'b>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - parent_substs: &[subst::GenericArg<'tcx>], - has_self: bool, - self_ty: Option>, - arg_count: GenericArgCountResult, - args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), - mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, - mut inferred_kind: impl FnMut( - Option<&[subst::GenericArg<'tcx>]>, - &GenericParamDef, - bool, - ) -> subst::GenericArg<'tcx>, - ) -> SubstsRef<'tcx> { - // Collect the segments of the path; we need to substitute arguments - // for parameters throughout the entire path (wherever there are - // generic parameters). - let mut parent_defs = tcx.generics_of(def_id); - let count = parent_defs.count(); - let mut stack = vec![(def_id, parent_defs)]; - while let Some(def_id) = parent_defs.parent { - parent_defs = tcx.generics_of(def_id); - stack.push((def_id, parent_defs)); - } - - // We manually build up the substitution, rather than using convenience - // methods in `subst.rs`, so that we can iterate over the arguments and - // parameters in lock-step linearly, instead of trying to match each pair. - let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); - // Iterate over each segment of the path. - while let Some((def_id, defs)) = stack.pop() { - let mut params = defs.params.iter().peekable(); - - // If we have already computed substitutions for parents, we can use those directly. - while let Some(¶m) = params.peek() { - if let Some(&kind) = parent_substs.get(param.index as usize) { - substs.push(kind); - params.next(); - } else { - break; - } - } - - // `Self` is handled first, unless it's been handled in `parent_substs`. - if has_self { - if let Some(¶m) = params.peek() { - if param.index == 0 { - if let GenericParamDefKind::Type { .. } = param.kind { - substs.push( - self_ty - .map(|ty| ty.into()) - .unwrap_or_else(|| inferred_kind(None, param, true)), - ); - params.next(); - } - } - } - } - - // Check whether this segment takes generic arguments and the user has provided any. - let (generic_args, infer_args) = args_for_def_id(def_id); - - let mut args = - generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable(); - - // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. - // If we later encounter a lifetime, we know that the arguments were provided in the - // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be - // inferred, so we can use it for diagnostics later. - let mut force_infer_lt = None; - - loop { - // We're going to iterate through the generic arguments that the user - // provided, matching them with the generic parameters we expect. - // Mismatches can occur as a result of elided lifetimes, or for malformed - // input. We try to handle both sensibly. - match (args.peek(), params.peek()) { - (Some(&arg), Some(¶m)) => { - match (arg, ¶m.kind, arg_count.explicit_late_bound) { - (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) - | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) - | (GenericArg::Const(_), GenericParamDefKind::Const, _) => { - substs.push(provided_kind(param, arg)); - args.next(); - params.next(); - } - ( - GenericArg::Type(_) | GenericArg::Const(_), - GenericParamDefKind::Lifetime, - _, - ) => { - // We expected a lifetime argument, but got a type or const - // argument. That means we're inferring the lifetimes. - substs.push(inferred_kind(None, param, infer_args)); - force_infer_lt = Some(arg); - params.next(); - } - (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => { - // We've come across a lifetime when we expected something else in - // the presence of explicit late bounds. This is most likely - // due to the presence of the explicit bound so we're just going to - // ignore it. - args.next(); - } - (_, kind, _) => { - // We expected one kind of parameter, but the user provided - // another. This is an error. However, if we already know that - // the arguments don't match up with the parameters, we won't issue - // an additional error, as the user already knows what's wrong. - if arg_count.correct.is_ok() - && arg_count.explicit_late_bound == ExplicitLateBound::No - { - // We're going to iterate over the parameters to sort them out, and - // show that order to the user as a possible order for the parameters - let mut param_types_present = defs - .params - .clone() - .into_iter() - .map(|param| { - ( - match param.kind { - GenericParamDefKind::Lifetime => { - ParamKindOrd::Lifetime - } - GenericParamDefKind::Type { .. } => { - ParamKindOrd::Type - } - GenericParamDefKind::Const => { - ParamKindOrd::Const { - unordered: tcx - .sess - .features_untracked() - .const_generics, - } - } - }, - param, - ) - }) - .collect::>(); - param_types_present.sort_by_key(|(ord, _)| *ord); - let (mut param_types_present, ordered_params): ( - Vec, - Vec, - ) = param_types_present.into_iter().unzip(); - param_types_present.dedup(); - - Self::generic_arg_mismatch_err( - tcx.sess, - arg, - kind.descr(), - Some(&format!( - "reorder the arguments: {}: `<{}>`", - param_types_present - .into_iter() - .map(|ord| format!("{}s", ord.to_string())) - .collect::>() - .join(", then "), - ordered_params - .into_iter() - .filter_map(|param| { - if param.name == kw::SelfUpper { - None - } else { - Some(param.name.to_string()) - } - }) - .collect::>() - .join(", ") - )), - ); - } - - // We've reported the error, but we want to make sure that this - // problem doesn't bubble down and create additional, irrelevant - // errors. In this case, we're simply going to ignore the argument - // and any following arguments. The rest of the parameters will be - // inferred. - while args.next().is_some() {} - } - } - } - - (Some(&arg), None) => { - // We should never be able to reach this point with well-formed input. - // There are three situations in which we can encounter this issue. - // - // 1. The number of arguments is incorrect. In this case, an error - // will already have been emitted, and we can ignore it. - // 2. There are late-bound lifetime parameters present, yet the - // lifetime arguments have also been explicitly specified by the - // user. - // 3. We've inferred some lifetimes, which have been provided later (i.e. - // after a type or const). We want to throw an error in this case. - - if arg_count.correct.is_ok() - && arg_count.explicit_late_bound == ExplicitLateBound::No - { - let kind = arg.descr(); - assert_eq!(kind, "lifetime"); - let provided = - force_infer_lt.expect("lifetimes ought to have been inferred"); - Self::generic_arg_mismatch_err(tcx.sess, provided, kind, None); - } - - break; - } - - (None, Some(¶m)) => { - // If there are fewer arguments than parameters, it means - // we're inferring the remaining arguments. - substs.push(inferred_kind(Some(&substs), param, infer_args)); - params.next(); - } - - (None, None) => break, - } - } - } - - tcx.intern_substs(&substs) - } - /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete /// set of substitutions. This may involve applying defaulted type parameters. @@ -1023,79 +494,6 @@ 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. - fn complain_about_missing_type_params( - &self, - missing_type_params: Vec, - 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::>().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`. - 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(); - } - /// Instantiates the path for the given trait reference, assuming that it's /// bound to a valid trait type. Returns the `DefId` of the defining trait. /// The type _cannot_ be a type other than a trait type. @@ -1242,76 +640,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (substs, assoc_bindings, _) = self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); if let Some(b) = assoc_bindings.first() { - AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span); + Self::prohibit_assoc_ty_binding(self.tcx(), b.span); } ty::TraitRef::new(trait_def_id, substs) } - /// 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. - 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::, _>>() - .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(); - } - } - fn create_substs_for_ast_trait_ref<'a>( &self, span: Span, @@ -1912,196 +1245,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty } - /// 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. - fn complain_about_missing_associated_types( - &self, - associated_types: FxHashMap>, - potential_assoc_types: Vec, - 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> = 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 = 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` - // - // 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` - [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` instead of - // `Iterator`. - 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`. - 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(); - } - fn report_ambiguous_associated_type( &self, span: Span, @@ -2289,52 +1432,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ok(bound) } - fn complain_about_assoc_type_not_found( - &self, - all_candidates: impl Fn() -> I, - ty_param_name: &str, - assoc_name: Ident, - span: Span, - ) where - I: Iterator>, - { - // 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(); - } - // Create a type from a path to an associated type. // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for @@ -2637,57 +1734,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { has_err } - pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { - let mut err = struct_span_err!( - tcx.sess, - span, - E0229, - "associated type bindings are not allowed here" - ); - err.span_label(span, "associated type not allowed here").emit(); - } - - /// Prohibits explicit lifetime arguments if late-bound lifetime parameters - /// are present. This is used both for datatypes and function calls. - fn prohibit_explicit_late_bound_lifetimes( - tcx: TyCtxt<'_>, - def: &ty::Generics, - args: &hir::GenericArgs<'_>, - position: GenericArgPosition, - ) -> ExplicitLateBound { - let param_counts = def.own_counts(); - let arg_counts = args.own_counts(); - let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; - - if infer_lifetimes { - ExplicitLateBound::No - } else if let Some(span_late) = def.has_late_bound_regions { - let msg = "cannot specify lifetime arguments explicitly \ - if late bound lifetime parameters are present"; - let note = "the late bound lifetime parameter is introduced here"; - let span = args.args[0].span(); - if position == GenericArgPosition::Value - && arg_counts.lifetimes != param_counts.lifetimes - { - let mut err = tcx.sess.struct_span_err(span, msg); - err.span_note(span_late, note); - err.emit(); - } else { - let mut multispan = MultiSpan::from_span(span); - multispan.push_span_label(span_late, note.to_string()); - tcx.struct_span_lint_hir( - LATE_BOUND_LIFETIME_ARGUMENTS, - args.args[0].id(), - multispan, - |lint| lint.build(msg).emit(), - ); - } - ExplicitLateBound::Yes - } else { - ExplicitLateBound::No - } - } - // FIXME(eddyb, varkor) handle type paths here too, not just value ones. pub fn def_ids_for_value_path_segments( &self, @@ -3248,92 +2294,3 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(r) } } - -/// Collects together a list of bounds that are applied to some type, -/// after they've been converted into `ty` form (from the HIR -/// representations). 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() { } -/// ^^^^^^^^^ 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 -#[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` this would include `::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, -} - -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() - } -} diff --git a/src/librustc_typeck/bounds.rs b/src/librustc_typeck/bounds.rs new file mode 100644 index 0000000000000..63295f5faacc9 --- /dev/null +++ b/src/librustc_typeck/bounds.rs @@ -0,0 +1,93 @@ +//! 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() { } +/// ^^^^^^^^^ 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` this would include `::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, +} + +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() + } +} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7fb4026117be9..9afac60bb5bb7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4248253172598..62f92fe7ffa48 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -79,6 +79,7 @@ pub mod check; pub mod expr_use_visitor; mod astconv; +mod bounds; mod check_unused; mod coherence; mod collect; @@ -109,7 +110,8 @@ use rustc_trait_selection::traits::{ 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) { diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 0a836f46c0eb8..457359e7a3806 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -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 @@ impl ItemCount { } fn examples_percentage(&self) -> Option { - 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 @@ impl ops::Sub for ItemCount { 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 @@ impl CoverageCalculator { 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 @@ impl CoverageCalculator { 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 @@ impl CoverageCalculator { impl fold::DocFolder for CoverageCalculator { fn fold_item(&mut self, i: clean::Item) -> Option { - 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::>().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 @@ impl fold::DocFolder for CoverageCalculator { } } _ => { + 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::>().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, + ); } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 97b9fcce05b36..9c57435a8c016 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -636,7 +636,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } match disambiguator.map(Disambiguator::ns) { - Some(ns @ ValueNS) => { + Some(ns @ (ValueNS | TypeNS)) => { match self.resolve( path_str, disambiguator, @@ -660,28 +660,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } } - Some(ns @ TypeNS) => { - match self.resolve( - path_str, - disambiguator, - ns, - ¤t_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 { diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs index a8df350ef60b2..e39f74c916c4a 100644 --- a/src/test/assembly/asm/aarch64-types.rs +++ b/src/test/assembly/asm/aarch64-types.rs @@ -553,3 +553,8 @@ check_reg!(v0_f32x4 f32x4 "s0" "fmov"); // 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") _); +} diff --git a/src/test/rustdoc-ui/coverage/basic.stdout b/src/test/rustdoc-ui/coverage/basic.stdout index 7e795acc575bc..3c602b3da4c7c 100644 --- a/src/test/rustdoc-ui/coverage/basic.stdout +++ b/src/test/rustdoc-ui/coverage/basic.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.rs b/src/test/rustdoc-ui/coverage/doc-examples-json.rs new file mode 100644 index 0000000000000..1da1813790e86 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/doc-examples-json.rs @@ -0,0 +1,13 @@ +// 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; diff --git a/src/test/rustdoc-ui/coverage/doc-examples-json.stdout b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout new file mode 100644 index 0000000000000..92f58556975ae --- /dev/null +++ b/src/test/rustdoc-ui/coverage/doc-examples-json.stdout @@ -0,0 +1 @@ +{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}} diff --git a/src/test/rustdoc-ui/coverage/doc-examples.stdout b/src/test/rustdoc-ui/coverage/doc-examples.stdout index f25cf79a3f35d..10ed13c9ff566 100644 --- a/src/test/rustdoc-ui/coverage/doc-examples.stdout +++ b/src/test/rustdoc-ui/coverage/doc-examples.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/empty.stdout b/src/test/rustdoc-ui/coverage/empty.stdout index 2a6a2231e5b57..890a7d56e162d 100644 --- a/src/test/rustdoc-ui/coverage/empty.stdout +++ b/src/test/rustdoc-ui/coverage/empty.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout index dd86f61f8d501..64c012c1f66e3 100644 --- a/src/test/rustdoc-ui/coverage/enums.stdout +++ b/src/test/rustdoc-ui/coverage/enums.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/exotic.stdout b/src/test/rustdoc-ui/coverage/exotic.stdout index f920a3abd36bb..e282ff1284375 100644 --- a/src/test/rustdoc-ui/coverage/exotic.stdout +++ b/src/test/rustdoc-ui/coverage/exotic.stdout @@ -1,8 +1,8 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| File | Documented | Total | Percentage | Examples | Percentage | -+-------------------------------------+------------+------------+------------+------------+------------+ -| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% | 0 | 0.0% | -| | 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% | +| | 2 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 3 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs index 2bd6a312ab583..a591cd5dba406 100644 --- a/src/test/rustdoc-ui/coverage/json.rs +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -12,16 +12,54 @@ pub mod foo { 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 { + /// ``` + /// 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; diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout index 7b5b083e1584c..c2be73ce3edd7 100644 --- a/src/test/rustdoc-ui/coverage/json.stdout +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -1 +1 @@ -{"$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}} diff --git a/src/test/rustdoc-ui/coverage/private.stdout b/src/test/rustdoc-ui/coverage/private.stdout index bca3d51da59d0..37a0f5187b512 100644 --- a/src/test/rustdoc-ui/coverage/private.stdout +++ b/src/test/rustdoc-ui/coverage/private.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/statics-consts.stdout b/src/test/rustdoc-ui/coverage/statics-consts.stdout index 31b48cc602a76..dbea3a3ea23cf 100644 --- a/src/test/rustdoc-ui/coverage/statics-consts.stdout +++ b/src/test/rustdoc-ui/coverage/statics-consts.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/traits.stdout b/src/test/rustdoc-ui/coverage/traits.stdout index ac63b65023d0b..e04d48b4980c4 100644 --- a/src/test/rustdoc-ui/coverage/traits.stdout +++ b/src/test/rustdoc-ui/coverage/traits.stdout @@ -1,7 +1,7 @@ -+-------------------------------------+------------+------------+------------+------------+------------+ -| 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% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index 6962ccdec73ee..8a6f7de1c9fbd 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -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)] diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 32233a0f6eeb7..dc2661ee79685 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -1,5 +1,5 @@ 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); | -^^^^^^^