]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #75790 - LeSeulArtichaut:std-intra-doc, r=jyn514
authorbors <bors@rust-lang.org>
Sat, 22 Aug 2020 08:54:29 +0000 (08:54 +0000)
committerbors <bors@rust-lang.org>
Sat, 22 Aug 2020 08:54:29 +0000 (08:54 +0000)
Use intra-doc-links in `std::sync::*`

Helps with #75080.
r? @jyn514

66 files changed:
library/alloc/src/alloc.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/fmt.rs
library/alloc/src/lib.rs
library/alloc/src/macros.rs
library/alloc/src/rc.rs
library/alloc/src/slice.rs
library/alloc/src/sync.rs
library/core/src/intrinsics.rs
library/core/src/ops/deref.rs
library/core/src/ops/drop.rs
library/core/src/ops/function.rs
library/core/src/ops/index.rs
library/core/src/ops/mod.rs
library/core/src/ops/range.rs
library/core/src/ops/unsize.rs
library/core/src/str/pattern.rs
library/std/src/io/stdio.rs
library/std/src/sys/cloudabi/stdio.rs
library/std/src/sys/hermit/stdio.rs
library/std/src/sys/sgx/stdio.rs
library/std/src/sys/unix/stdio.rs
library/std/src/sys/unsupported/stdio.rs
library/std/src/sys/vxworks/stdio.rs
library/std/src/sys/wasi/stdio.rs
library/std/src/sys/windows/stdio.rs
library/std/src/sys/windows/stdio_uwp.rs
src/bootstrap/config.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/format.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
src/librustc_codegen_llvm/asm.rs
src/librustc_lexer/src/tests.rs
src/librustc_middle/mir/terminator/mod.rs
src/librustc_typeck/astconv.rs [deleted file]
src/librustc_typeck/astconv/errors.rs [new file with mode: 0644]
src/librustc_typeck/astconv/generics.rs [new file with mode: 0644]
src/librustc_typeck/astconv/mod.rs [new file with mode: 0644]
src/librustc_typeck/bounds.rs [new file with mode: 0644]
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/doc_test_lints.rs
src/test/assembly/asm/aarch64-types.rs
src/test/rustdoc-ui/coverage/basic.stdout
src/test/rustdoc-ui/coverage/doc-examples-json.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/doc-examples-json.stdout [new file with mode: 0644]
src/test/rustdoc-ui/coverage/doc-examples.stdout
src/test/rustdoc-ui/coverage/empty.stdout
src/test/rustdoc-ui/coverage/enums.stdout
src/test/rustdoc-ui/coverage/exotic.stdout
src/test/rustdoc-ui/coverage/json.rs
src/test/rustdoc-ui/coverage/json.stdout
src/test/rustdoc-ui/coverage/private.stdout
src/test/rustdoc-ui/coverage/statics-consts.stdout
src/test/rustdoc-ui/coverage/traits.stdout
src/test/rustdoc-ui/lint-missing-doc-code-example.rs
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
src/test/ui/consts/const-eval/const-eval-query-stack.rs
src/test/ui/consts/const-eval/const-eval-query-stack.stderr

index fa5eb1823f1a0755c721abbed9a13b5e5e5a0b84..87b86e590a4c82b23e5d4d5a030eef7c53057728 100644 (file)
@@ -36,8 +36,6 @@
 ///
 /// Note: while this type is unstable, the functionality it provides can be
 /// accessed through the [free functions in `alloc`](index.html#functions).
-///
-/// [`AllocRef`]: trait.AllocRef.html
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[derive(Copy, Clone, Default, Debug)]
 pub struct Global;
 ///
 /// 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
 ///
 /// ```
index 5e304beff78ab1cb469ce5bdab2e24a2004e4407..93d0df448ea1447f3bfbb7d8c832bbda8b737152 100644 (file)
 //! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
 //!
 //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
-//! [dereferencing]: ../../std/ops/trait.Deref.html
-//! [`Box`]: struct.Box.html
-//! [`Box<T>`]: struct.Box.html
-//! [`Box::<T>::from_raw(value)`]: struct.Box.html#method.from_raw
-//! [`Box::<T>::into_raw`]: struct.Box.html#method.into_raw
-//! [`Global`]: ../alloc/struct.Global.html
-//! [`Layout`]: ../alloc/struct.Layout.html
-//! [`Layout::for_value(&*value)`]: ../alloc/struct.Layout.html#method.for_value
+//! [dereferencing]: core::ops::Deref
+//! [`Box<T>`]: Box
+//! [`Box::<T>::from_raw(value)`]: Box::from_raw
+//! [`Box::<T>::into_raw`]: Box::into_raw
+//! [`Global`]: crate::alloc::Global
+//! [`Layout`]: crate::alloc::Layout
+//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -240,7 +239,6 @@ pub fn pin(x: T) -> Pin<Box<T>> {
     /// Converts a `Box<T>` into a `Box<[T]>`
     ///
     /// This conversion does not allocate on the heap and happens in place.
-    ///
     #[unstable(feature = "box_into_boxed_slice", issue = "71582")]
     pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
         // *mut T and *mut [T; 1] have the same size and alignment
@@ -386,9 +384,8 @@ impl<T: ?Sized> Box<T> {
     /// }
     /// ```
     ///
-    /// [memory layout]: index.html#memory-layout
-    /// [`Layout`]: ../alloc/struct.Layout.html
-    /// [`Box::into_raw`]: struct.Box.html#method.into_raw
+    /// [memory layout]: self#memory-layout
+    /// [`Layout`]: crate::Layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
@@ -433,8 +430,7 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
     /// }
     /// ```
     ///
-    /// [memory layout]: index.html#memory-layout
-    /// [`Box::from_raw`]: struct.Box.html#method.from_raw
+    /// [memory layout]: self#memory-layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub fn into_raw(b: Box<T>) -> *mut T {
@@ -478,8 +474,6 @@ pub fn into_unique(b: Box<T>) -> Unique<T> {
     /// to call it as `Box::leak(b)` instead of `b.leak()`. This
     /// is so that there is no conflict with a method on the inner type.
     ///
-    /// [`Box::from_raw`]: struct.Box.html#method.from_raw
-    ///
     /// # Examples
     ///
     /// Simple usage:
index 02a746f0e24880893ff89f1983bada892057ae41..5390b57a1d98dddcd84ef1e2dfc0e7896c1ddd20 100644 (file)
@@ -7,8 +7,8 @@
 //! array-based containers are generally faster,
 //! more memory efficient, and make better use of CPU cache.
 //!
-//! [`Vec`]: ../../vec/struct.Vec.html
-//! [`VecDeque`]: ../vec_deque/struct.VecDeque.html
+//! [`Vec`]: crate::vec::Vec
+//! [`VecDeque`]: super::vec_deque::VecDeque
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -50,11 +50,8 @@ struct Node<T> {
 
 /// An iterator over the elements of a `LinkedList`.
 ///
-/// This `struct` is created by the [`iter`] method on [`LinkedList`]. See its
+/// This `struct` is created by [`LinkedList::iter()`]. See its
 /// documentation for more.
-///
-/// [`iter`]: struct.LinkedList.html#method.iter
-/// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     head: Option<NonNull<Node<T>>>,
@@ -80,11 +77,8 @@ fn clone(&self) -> Self {
 
 /// A mutable iterator over the elements of a `LinkedList`.
 ///
-/// This `struct` is created by the [`iter_mut`] method on [`LinkedList`]. See its
+/// This `struct` is created by [`LinkedList::iter_mut()`]. See its
 /// documentation for more.
-///
-/// [`iter_mut`]: struct.LinkedList.html#method.iter_mut
-/// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     // We do *not* exclusively own the entire list here, references to node's `element`
@@ -109,7 +103,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// (provided by the `IntoIterator` trait). See its documentation for more.
 ///
 /// [`into_iter`]: struct.LinkedList.html#method.into_iter
-/// [`LinkedList`]: struct.LinkedList.html
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
index a0b151a4496f114c86d3530990b16c73012c82eb..a886e17f5a9c3022a07467ccdded6bdec6e9c7b0 100644 (file)
 //! 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")]
 
 /// 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();
index 2d25941a52412187c8a43f1bb03c25fb865eb3ab..892f794fc42326909cc4301605228af25067fc6c 100644 (file)
 //! 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")]
index e163a166b498fceab4aa669f23d3069f76195629..2f744618d6936937224ee92fe41c1ac9f9b545ac 100644 (file)
@@ -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
 ///
index d0a47ccea0a76f96fabc05773bb226bd74d69a37..f8b1c21e9771c3324823a27a20d1087d9d9d7663 100644 (file)
 //! }
 //! ```
 //!
-//! [`Rc`]: struct.Rc.html
-//! [`Weak`]: struct.Weak.html
-//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
-//! [`Cell`]: ../../std/cell/struct.Cell.html
-//! [`RefCell`]: ../../std/cell/struct.RefCell.html
-//! [send]: ../../std/marker/trait.Send.html
+//! [clone]: Clone::clone
+//! [`Cell`]: core::cell::Cell
+//! [`RefCell`]: core::cell::RefCell
+//! [send]: core::marker::Send
 //! [arc]: ../../std/sync/struct.Arc.html
-//! [`Deref`]: ../../std/ops/trait.Deref.html
-//! [downgrade]: struct.Rc.html#method.downgrade
-//! [upgrade]: struct.Weak.html#method.upgrade
-//! [`None`]: ../../std/option/enum.Option.html#variant.None
-//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
+//! [`Deref`]: core::ops::Deref
+//! [downgrade]: Rc::downgrade
+//! [upgrade]: Weak::upgrade
+//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -396,13 +393,11 @@ pub fn pin(value: T) -> Pin<Rc<T>> {
 
     /// Returns the inner value, if the `Rc` has exactly one strong reference.
     ///
-    /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
+    /// Otherwise, an [`Err`] is returned with the same `Rc` that was
     /// passed in.
     ///
     /// This will succeed even if there are outstanding weak references.
     ///
-    /// [result]: ../../std/result/enum.Result.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -553,7 +548,7 @@ impl<T: ?Sized> Rc<T> {
     /// To avoid a memory leak the pointer must be converted back to an `Rc` using
     /// [`Rc::from_raw`][from_raw].
     ///
-    /// [from_raw]: struct.Rc.html#method.from_raw
+    /// [from_raw]: Rc::from_raw
     ///
     /// # Examples
     ///
@@ -613,8 +608,8 @@ pub fn as_ptr(this: &Self) -> *const T {
     /// This function is unsafe because improper use may lead to memory unsafety,
     /// even if the returned `Rc<T>` is never accessed.
     ///
-    /// [into_raw]: struct.Rc.html#method.into_raw
-    /// [transmute]: ../../std/mem/fn.transmute.html
+    /// [into_raw]: Rc::into_raw
+    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
@@ -645,9 +640,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         unsafe { Self::from_ptr(rc_ptr) }
     }
 
-    /// Creates a new [`Weak`][weak] pointer to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Creates a new [`Weak`] pointer to this allocation.
     ///
     /// # Examples
     ///
@@ -666,9 +659,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
         Weak { ptr: this.ptr }
     }
 
-    /// Gets the number of [`Weak`][weak] pointers to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Gets the number of [`Weak`] pointers to this allocation.
     ///
     /// # Examples
     ///
@@ -704,17 +695,15 @@ pub fn strong_count(this: &Self) -> usize {
         this.strong()
     }
 
-    /// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to
+    /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to
     /// this allocation.
-    ///
-    /// [weak]: struct.Weak.html
     #[inline]
     fn is_unique(this: &Self) -> bool {
         Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
     }
 
     /// Returns a mutable reference into the given `Rc`, if there are
-    /// no other `Rc` or [`Weak`][weak] pointers to the same allocation.
+    /// no other `Rc` or [`Weak`] pointers to the same allocation.
     ///
     /// Returns [`None`] otherwise, because it is not safe to
     /// mutate a shared value.
@@ -722,10 +711,8 @@ fn is_unique(this: &Self) -> bool {
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
     /// the inner value when there are other pointers.
     ///
-    /// [weak]: struct.Weak.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [make_mut]: struct.Rc.html#method.make_mut
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [make_mut]: Rc::make_mut
+    /// [clone]: Clone::clone
     ///
     /// # Examples
     ///
@@ -750,7 +737,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     ///
     /// See also [`get_mut`], which is safe and does appropriate checks.
     ///
-    /// [`get_mut`]: struct.Rc.html#method.get_mut
+    /// [`get_mut`]: Rc::get_mut
     ///
     /// # Safety
     ///
@@ -796,7 +783,7 @@ pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
     /// assert!(!Rc::ptr_eq(&five, &other_five));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
         this.ptr.as_ptr() == other.ptr.as_ptr()
     }
@@ -814,9 +801,8 @@ impl<T: Clone> Rc<T> {
     ///
     /// See also [`get_mut`], which will fail rather than cloning.
     ///
-    /// [`Weak`]: struct.Weak.html
-    /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone
-    /// [`get_mut`]: struct.Rc.html#method.get_mut
+    /// [`clone`]: Clone::clone
+    /// [`get_mut`]: Rc::get_mut
     ///
     /// # Examples
     ///
@@ -1117,8 +1103,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
     /// drop(foo);    // Doesn't print anything
     /// drop(foo2);   // Prints "dropped!"
     /// ```
-    ///
-    /// [`Weak`]: ../../std/rc/struct.Weak.html
     fn drop(&mut self) {
         unsafe {
             self.dec_strong();
@@ -1600,11 +1584,7 @@ fn to_rc_slice(self) -> Rc<[T]> {
 ///
 /// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`].
 ///
-/// [`Rc`]: struct.Rc.html
-/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade
-/// [`upgrade`]: struct.Weak.html#method.upgrade
-/// [`Option`]: ../../std/option/enum.Option.html
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
+/// [`upgrade`]: Weak::upgrade
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     // This is a `NonNull` to allow optimizing the size of this type in enums,
@@ -1631,8 +1611,7 @@ impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`upgrade`]: #method.upgrade
-    /// [`None`]: ../../std/option/enum.Option.html
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
@@ -1671,7 +1650,7 @@ pub fn new() -> Weak<T> {
     /// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
+    /// [`null`]: core::ptr::null
     #[stable(feature = "rc_as_ptr", since = "1.45.0")]
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
@@ -1713,8 +1692,8 @@ pub fn as_ptr(&self) -> *const T {
     /// assert_eq!(0, Rc::weak_count(&strong));
     /// ```
     ///
-    /// [`from_raw`]: struct.Weak.html#method.from_raw
-    /// [`as_ptr`]: struct.Weak.html#method.as_ptr
+    /// [`from_raw`]: Weak::from_raw
+    /// [`as_ptr`]: Weak::as_ptr
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
@@ -1761,12 +1740,9 @@ pub fn into_raw(self) -> *const T {
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`into_raw`]: struct.Weak.html#method.into_raw
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`Rc`]: struct.Rc.html
-    /// [`Weak`]: struct.Weak.html
-    /// [`new`]: struct.Weak.html#method.new
-    /// [`forget`]: ../../std/mem/fn.forget.html
+    /// [`into_raw`]: Weak::into_raw
+    /// [`upgrade`]: Weak::upgrade
+    /// [`new`]: Weak::new
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
@@ -1794,9 +1770,6 @@ impl<T: ?Sized> Weak<T> {
     ///
     /// Returns [`None`] if the inner value has since been dropped.
     ///
-    /// [`Rc`]: struct.Rc.html
-    /// [`None`]: ../../std/option/enum.Option.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -1829,8 +1802,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     /// Gets the number of strong (`Rc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong() } else { 0 }
@@ -1899,7 +1870,7 @@ fn inner(&self) -> Option<&RcBox<T>> {
     /// assert!(!first.ptr_eq(&third));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     #[inline]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
@@ -1981,8 +1952,8 @@ impl<T> Default for Weak<T> {
     /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
     /// it. Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html
-    /// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade
+    /// [`None`]: Option
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
index b791c775548cda7f8f81f013ad0f38e566e493da..8ea2c6dc859b274c4afa9764e777a7f488f68a77 100644 (file)
 //! * Further methods that return iterators are [`.split`], [`.splitn`],
 //!   [`.chunks`], [`.windows`] and more.
 //!
-//! [`Clone`]: ../../std/clone/trait.Clone.html
-//! [`Eq`]: ../../std/cmp/trait.Eq.html
-//! [`Ord`]: ../../std/cmp/trait.Ord.html
-//! [`Iter`]: struct.Iter.html
-//! [`Hash`]: ../../std/hash/trait.Hash.html
+//! [`Hash`]: core::hash::Hash
 //! [`.iter`]: ../../std/primitive.slice.html#method.iter
 //! [`.iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
 //! [`.split`]: ../../std/primitive.slice.html#method.split
@@ -560,7 +556,7 @@ impl [u8] {
     ///
     /// To uppercase the value in-place, use [`make_ascii_uppercase`].
     ///
-    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`make_ascii_uppercase`]: u8::make_ascii_uppercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_uppercase(&self) -> Vec<u8> {
@@ -577,7 +573,7 @@ pub fn to_ascii_uppercase(&self) -> Vec<u8> {
     ///
     /// To lowercase the value in-place, use [`make_ascii_lowercase`].
     ///
-    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`make_ascii_lowercase`]: u8::make_ascii_lowercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_lowercase(&self) -> Vec<u8> {
index b37633031375883844506603a0e2c2872c699a09..4444a7a313298f25e047183b3376d58f68198170 100644 (file)
@@ -2,9 +2,7 @@
 
 //! Thread-safe reference-counting pointers.
 //!
-//! See the [`Arc<T>`][arc] documentation for more details.
-//!
-//! [arc]: struct.Arc.html
+//! See the [`Arc<T>`][Arc] documentation for more details.
 
 use core::any::Any;
 use core::borrow;
@@ -100,21 +98,21 @@ 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<T>`][arc] and [`Weak<T>`][weak].
+/// `Clone` trait implemented for [`Arc<T>`][Arc] and [`Weak<T>`][Weak].
 ///
 /// ```
 /// use std::sync::Arc;
@@ -139,23 +137,20 @@ macro_rules! acquire {
 /// Arc::downgrade(&my_arc);
 /// ```
 ///
-/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the inner value may have
+/// [`Weak<T>`][Weak] does not auto-dereference to `T`, because the inner value may have
 /// already been dropped.
 ///
-/// [arc]: struct.Arc.html
-/// [weak]: struct.Weak.html
-/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
-/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+/// [`Rc<T>`]: crate::rc::Rc
+/// [clone]: Clone::clone
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
-/// [atomic]: ../../std/sync/atomic/index.html
-/// [`Send`]: ../../std/marker/trait.Send.html
-/// [`Sync`]: ../../std/marker/trait.Sync.html
-/// [deref]: ../../std/ops/trait.Deref.html
-/// [downgrade]: struct.Arc.html#method.downgrade
-/// [upgrade]: struct.Weak.html#method.upgrade
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
-/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
+/// [atomic]: core::sync::atomic
+/// [`Send`]: core::marker::Send
+/// [`Sync`]: core::marker::Sync
+/// [deref]: core::ops::Deref
+/// [downgrade]: Arc::downgrade
+/// [upgrade]: Weak::upgrade
+/// [`RefCell<T>`]: core::cell::RefCell
 /// [`std::sync`]: ../../std/sync/index.html
 /// [`Arc::clone(&from)`]: #method.clone
 ///
@@ -184,7 +179,7 @@ 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 @@ unsafe fn from_ptr(ptr: *mut ArcInner<T>) -> Self {
 ///
 /// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`].
 ///
-/// [`Arc`]: struct.Arc.html
-/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade
-/// [`upgrade`]: struct.Weak.html#method.upgrade
-/// [`Option`]: ../../std/option/enum.Option.html
-/// [`None`]: ../../std/option/enum.Option.html#variant.None
+/// [`upgrade`]: Weak::upgrade
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
     // This is a `NonNull` to allow optimizing the size of this type in enums,
@@ -396,13 +387,11 @@ pub fn pin(data: T) -> Pin<Arc<T>> {
 
     /// Returns the inner value, if the `Arc` has exactly one strong reference.
     ///
-    /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
+    /// Otherwise, an [`Err`] is returned with the same `Arc` that was
     /// passed in.
     ///
     /// This will succeed even if there are outstanding weak references.
     ///
-    /// [result]: ../../std/result/enum.Result.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -550,9 +539,7 @@ impl<T: ?Sized> Arc<T> {
     /// Consumes the `Arc`, returning the wrapped pointer.
     ///
     /// To avoid a memory leak the pointer must be converted back to an `Arc` using
-    /// [`Arc::from_raw`][from_raw].
-    ///
-    /// [from_raw]: struct.Arc.html#method.from_raw
+    /// [`Arc::from_raw`].
     ///
     /// # Examples
     ///
@@ -612,8 +599,8 @@ pub fn as_ptr(this: &Self) -> *const T {
     /// This function is unsafe because improper use may lead to memory unsafety,
     /// even if the returned `Arc<T>` is never accessed.
     ///
-    /// [into_raw]: struct.Arc.html#method.into_raw
-    /// [transmute]: ../../std/mem/fn.transmute.html
+    /// [into_raw]: Arc::into_raw
+    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
@@ -646,9 +633,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         }
     }
 
-    /// Creates a new [`Weak`][weak] pointer to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Creates a new [`Weak`] pointer to this allocation.
     ///
     /// # Examples
     ///
@@ -690,9 +675,7 @@ pub fn downgrade(this: &Self) -> Weak<T> {
         }
     }
 
-    /// Gets the number of [`Weak`][weak] pointers to this allocation.
-    ///
-    /// [weak]: struct.Weak.html
+    /// Gets the number of [`Weak`] pointers to this allocation.
     ///
     /// # Safety
     ///
@@ -861,7 +844,7 @@ unsafe fn drop_slow(&mut self) {
     /// assert!(!Arc::ptr_eq(&five, &other_five));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
         this.ptr.as_ptr() == other.ptr.as_ptr()
     }
@@ -1098,7 +1081,7 @@ impl<T: ?Sized> Receiver for Arc<T> {}
 impl<T: Clone> Arc<T> {
     /// Makes a mutable reference into the given `Arc`.
     ///
-    /// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation,
+    /// If there are other `Arc` or [`Weak`] pointers to the same allocation,
     /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
     /// to ensure unique ownership. This is also referred to as clone-on-write.
     ///
@@ -1107,10 +1090,9 @@ impl<T: Clone> Arc<T> {
     ///
     /// See also [`get_mut`][get_mut], which will fail rather than cloning.
     ///
-    /// [weak]: struct.Weak.html
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
-    /// [get_mut]: struct.Arc.html#method.get_mut
-    /// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut
+    /// [clone]: Clone::clone
+    /// [get_mut]: Arc::get_mut
+    /// [`Rc::make_mut`]: super::rc::Rc::make_mut
     ///
     /// # Examples
     ///
@@ -1184,18 +1166,16 @@ pub fn make_mut(this: &mut Self) -> &mut T {
 
 impl<T: ?Sized> Arc<T> {
     /// Returns a mutable reference into the given `Arc`, if there are
-    /// no other `Arc` or [`Weak`][weak] pointers to the same allocation.
+    /// no other `Arc` or [`Weak`] pointers to the same allocation.
     ///
-    /// Returns [`None`][option] otherwise, because it is not safe to
+    /// Returns [`None`] otherwise, because it is not safe to
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
     /// the inner value when there are other pointers.
     ///
-    /// [weak]: struct.Weak.html
-    /// [option]: ../../std/option/enum.Option.html
-    /// [make_mut]: struct.Arc.html#method.make_mut
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [make_mut]: Arc::make_mut
+    /// [clone]: Clone::clone
     ///
     /// # Examples
     ///
@@ -1229,7 +1209,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
     ///
     /// See also [`get_mut`], which is safe and does appropriate checks.
     ///
-    /// [`get_mut`]: struct.Arc.html#method.get_mut
+    /// [`get_mut`]: Arc::get_mut
     ///
     /// # Safety
     ///
@@ -1315,8 +1295,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
     /// drop(foo);    // Doesn't print anything
     /// drop(foo2);   // Prints "dropped!"
     /// ```
-    ///
-    /// [`Weak`]: ../../std/sync/struct.Weak.html
     #[inline]
     fn drop(&mut self) {
         // Because `fetch_sub` is already atomic, we do not need to synchronize
@@ -1401,8 +1379,7 @@ impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`] on the return value always gives [`None`].
     ///
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
@@ -1441,7 +1418,7 @@ pub fn new() -> Weak<T> {
     /// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
     /// ```
     ///
-    /// [`null`]: ../../std/ptr/fn.null.html
+    /// [`null`]: core::ptr::null
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn as_ptr(&self) -> *const T {
         let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
@@ -1483,8 +1460,8 @@ pub fn as_ptr(&self) -> *const T {
     /// assert_eq!(0, Arc::weak_count(&strong));
     /// ```
     ///
-    /// [`from_raw`]: struct.Weak.html#method.from_raw
-    /// [`as_ptr`]: struct.Weak.html#method.as_ptr
+    /// [`from_raw`]: Weak::from_raw
+    /// [`as_ptr`]: Weak::as_ptr
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
@@ -1530,12 +1507,10 @@ pub fn into_raw(self) -> *const T {
     /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
-    /// [`new`]: struct.Weak.html#method.new
-    /// [`into_raw`]: struct.Weak.html#method.into_raw
-    /// [`upgrade`]: struct.Weak.html#method.upgrade
-    /// [`Weak`]: struct.Weak.html
-    /// [`Arc`]: struct.Arc.html
-    /// [`forget`]: ../../std/mem/fn.forget.html
+    /// [`new`]: Weak::new
+    /// [`into_raw`]: Weak::into_raw
+    /// [`upgrade`]: Weak::upgrade
+    /// [`forget`]: std::mem::forget
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
         if ptr.is_null() {
@@ -1565,9 +1540,6 @@ impl<T: ?Sized> Weak<T> {
     ///
     /// Returns [`None`] if the inner value has since been dropped.
     ///
-    /// [`Arc`]: struct.Arc.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -1619,8 +1591,6 @@ pub fn upgrade(&self) -> Option<Arc<T>> {
     /// Gets the number of strong (`Arc`) pointers pointing to this allocation.
     ///
     /// If `self` was created using [`Weak::new`], this will return 0.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
         if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 }
@@ -1637,8 +1607,6 @@ pub fn strong_count(&self) -> usize {
     /// Due to implementation details, the returned value can be off by 1 in
     /// either direction when other threads are manipulating any `Arc`s or
     /// `Weak`s pointing to the same allocation.
-    ///
-    /// [`Weak::new`]: #method.new
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn weak_count(&self) -> usize {
         self.inner()
@@ -1716,7 +1684,7 @@ fn inner(&self) -> Option<WeakInner<'_>> {
     /// assert!(!first.ptr_eq(&third));
     /// ```
     ///
-    /// [`ptr::eq`]: ../../std/ptr/fn.eq.html
+    /// [`ptr::eq`]: core::ptr::eq
     #[inline]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
@@ -1765,8 +1733,7 @@ impl<T> Default for Weak<T> {
     /// Calling [`upgrade`] on the return value always
     /// gives [`None`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade
+    /// [`upgrade`]: Weak::upgrade
     ///
     /// # Examples
     ///
index 1399d0c020f16d8f7e86c36deb7fe2a54380f438..9acf43931c6bacfb59616385108d702bf59e1568 100644 (file)
 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",
     /// 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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(src: *const T) -> T;
     pub fn atomic_load_unordered<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(dst: *mut T, val: T);
     pub fn atomic_store_unordered<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(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<T: Copy>(dst: *mut T, src: T) -> T;
 
     /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
     /// 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();
 
     /// 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.
     /// 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.
     /// 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.
     /// 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();
 
     /// 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() -> !;
 
     /// 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<T>() -> usize;
 
     ///
     /// 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<T>(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<T>() -> usize;
     /// The preferred alignment of a type.
 
     /// 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<T: ?Sized>(_: *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<T: ?Sized>(_: *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<T: ?Sized>() -> &'static str;
 
     /// 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<T: ?Sized + 'static>() -> u64;
 
 
     /// 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: ?Sized>(_: T);
 
     /// Reinterprets the bits of a value of one type as another type.
     /// 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<T>() -> bool;
 
 
     /// 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<T>(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<T>(dst: *mut T, val: T);
 
     /// Performs a volatile load from the `src` pointer
     /// 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.
     /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
     /// (<https://github.com/rust-lang/rust/issues/10184>)
     ///
-    /// 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<Float: Copy, Int: Copy>(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<T: Copy>(x: T) -> T;
 
     ///
     /// 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
     ///
     ///
     /// 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
     ///
     ///
     /// 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<T: Copy>(x: T) -> T;
 
     ///
     /// 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<T: Copy>(x: T) -> T;
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> (T, bool);
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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<T: Copy>(x: T, y: T) -> T;
 
     ///
     /// 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<T: Copy>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, 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<T: Copy>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, 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<T: Copy>(a: T, b: T) -> T;
 
     ///
     /// 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<T: Copy>(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<T: Copy>(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<T>(v: &T) -> <T as DiscriminantKind>::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<T>() -> usize;
 
@@ -1989,7 +1762,6 @@ pub(crate) fn is_nonoverlapping<T>(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<T>(src: *const T, dst: *const T, count: usize) -
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) 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<T>(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<T>(src: *const T, dst: *mut T, count: usize) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) 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<T>(src: *const T, dst: *mut T, count: usize) {
 /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
 /// `0`, the pointer must be non-NULL and properly aligned.
 ///
-/// [valid]: ../ptr/index.html#safety
+/// [valid]: crate::ptr#safety
 ///
 /// # Examples
 ///
index 3faeb170b0637626090dcdb9dd1fba9c0b999cb3..d6c097eee17bf96ff18540667972043d8b1e86c8 100644 (file)
@@ -28,7 +28,6 @@
 /// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
-/// [`DerefMut`]: trait.DerefMut.html
 /// [more]: #more-on-deref-coercion
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
@@ -125,7 +124,6 @@ fn deref(&self) -> &T {
 /// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
-/// [`Deref`]: trait.Deref.html
 /// [more]: #more-on-deref-coercion
 /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
 /// [method resolution]: ../../reference/expressions/method-call-expr.html
index 06cfc36363615ee56515bcb64e439bea37676484..ce7d1c3d06ddc5dea1dfb68a152a7551c4d7e4af 100644 (file)
@@ -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
 ///
 /// 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);
 }
index 3e5cad2b185a14b252e5e2854e9ebfddc0cbfcce..bfdec43f7d80b3c211669655f1f54ae9f5ad6d48 100644 (file)
@@ -28,8 +28,6 @@
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`FnMut`]: trait.FnMut.html
-/// [`FnOnce`]: trait.FnOnce.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
@@ -99,8 +97,6 @@ pub trait Fn<Args>: FnMut<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`Fn`]: trait.Fn.html
-/// [`FnOnce`]: trait.FnOnce.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
@@ -180,8 +176,6 @@ pub trait FnMut<Args>: FnOnce<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [`Fn`]: trait.Fn.html
-/// [`FnMut`]: trait.FnMut.html
 /// [function pointers]: ../../std/primitive.fn.html
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
index 763b33606fe88b18c044359c74dec2c3bf6172e1..3c2ada57612337e0d865168bc7dc8b4d07af634b 100644 (file)
@@ -5,9 +5,6 @@
 /// [`IndexMut`] is used instead. This allows nice things such as
 /// `let value = v[index]` if the type of `value` implements [`Copy`].
 ///
-/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
-///
 /// # Examples
 ///
 /// The following example implements `Index` on a read-only `NucleotideCount`
@@ -76,8 +73,6 @@ pub trait Index<Idx: ?Sized> {
 /// an immutable value is requested, the [`Index`] trait is used instead. This
 /// allows nice things such as `v[index] = value`.
 ///
-/// [`Index`]: ../../std/ops/trait.Index.html
-///
 /// # Examples
 ///
 /// A very simple implementation of a `Balance` struct that has two sides, where
index e3e5934b44be1f0732913ce89568a556dc3d4e19..c19bd6e441e695950f5d258eabe83a816cdd9be3 100644 (file)
 //! // `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")]
index e9ab82b5398496d2996d8355b55090db6e0f33d9..ccabd66aaf6ebd738c13b9770dce99f299f84d91 100644 (file)
@@ -35,9 +35,7 @@
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeFull")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
@@ -178,8 +176,6 @@ pub fn is_empty(&self) -> bool {
 /// assert_eq!(arr[1.. 3], [  1,2    ]);
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
-///
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
 #[cfg_attr(not(bootstrap), lang = "RangeFrom")]
 #[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
@@ -260,9 +256,7 @@ pub fn contains<U>(&self, item: &U) -> bool
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeTo")]
 #[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -315,8 +309,8 @@ pub fn contains<U>(&self, item: &U) -> bool
 /// iteration has finished are **unspecified** other than that [`.is_empty()`]
 /// will return `true` once no more values will be produced.
 ///
-/// [fused]: ../iter/trait.FusedIterator.html
-/// [`.is_empty()`]: #method.is_empty
+/// [fused]: crate::iter::FusedIterator
+/// [`.is_empty()`]: RangeInclusive::is_empty
 ///
 /// # Examples
 ///
@@ -383,8 +377,8 @@ pub const fn new(start: Idx, end: Idx) -> Self {
     /// Note: the value returned by this method is unspecified after the range
     /// has been iterated to exhaustion.
     ///
-    /// [`end()`]: #method.end
-    /// [`is_empty()`]: #method.is_empty
+    /// [`end()`]: RangeInclusive::end
+    /// [`is_empty()`]: RangeInclusive::is_empty
     ///
     /// # Examples
     ///
@@ -408,8 +402,8 @@ pub const fn start(&self) -> &Idx {
     /// Note: the value returned by this method is unspecified after the range
     /// has been iterated to exhaustion.
     ///
-    /// [`start()`]: #method.start
-    /// [`is_empty()`]: #method.is_empty
+    /// [`start()`]: RangeInclusive::start
+    /// [`is_empty()`]: RangeInclusive::is_empty
     ///
     /// # Examples
     ///
@@ -558,9 +552,7 @@ pub fn is_empty(&self) -> bool {
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 ///
-/// [`IntoIterator`]: ../iter/trait.Iterator.html
-/// [`Iterator`]: ../iter/trait.IntoIterator.html
-/// [slicing index]: ../slice/trait.SliceIndex.html
+/// [slicing index]: crate::slice::SliceIndex
 #[cfg_attr(not(bootstrap), lang = "RangeToInclusive")]
 #[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
index 95a4393592be911f6565f5a434063f535818903e..483362023b22c77bc5f340260804f825c2766080 100644 (file)
@@ -29,7 +29,7 @@
 /// pointers. It is implemented automatically by the compiler.
 ///
 /// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
-/// [unsize]: ../marker/trait.Unsize.html
+/// [unsize]: crate::marker::Unsize
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 #[lang = "coerce_unsized"]
index 14f1f293d40d68716fd09e8ba5c6dd04db715114..1cc2de5b8756a8bdc8cc06e2fd26374aa1c45f90 100644 (file)
@@ -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`.
 //!
 //! ```
 //! 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(
 /// A string pattern.
 ///
 /// A `Pattern<'a>` expresses that the implementing type
-/// can be used as a string pattern for searching in a `&'a str`.
+/// can be used as a string pattern for searching in a [`&'a str`][str].
 ///
 /// For example, both `'a'` and `"aa"` are patterns that
 /// would match at index `1` in the string `"baaaab"`.
 ///
 /// The trait itself acts as a builder for an associated
-/// `Searcher` type, which does the actual work of finding
+/// [`Searcher`] type, which does the actual work of finding
 /// occurrences of the pattern in a string.
 ///
 /// Depending on the type of the pattern, the behaviour of methods like
@@ -75,6 +68,7 @@
 /// | `&String`                | is substring                              |
 ///
 /// # Examples
+///
 /// ```
 /// // &str
 /// assert_eq!("abaaa".find("ba"), Some(1));
@@ -94,9 +88,6 @@
 /// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4));
 /// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None);
 /// ```
-///
-/// [`str::find`]: ../../../std/primitive.str.html#method.find
-/// [`str::contains`]: ../../../std/primitive.str.html#method.contains
 pub trait Pattern<'a>: Sized {
     /// Associated searcher for this pattern
     type Searcher: Searcher<'a>;
@@ -165,7 +156,7 @@ fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
 
 // Searcher
 
-/// Result of calling `Searcher::next()` or `ReverseSearcher::next_back()`.
+/// Result of calling [`Searcher::next()`] or [`ReverseSearcher::next_back()`].
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
 pub enum SearchStep {
     /// Expresses that a match of the pattern has been found at
@@ -188,44 +179,47 @@ pub enum SearchStep {
 /// matches of a pattern starting from the front (left) of a string.
 ///
 /// It will be implemented by associated `Searcher`
-/// types of the `Pattern` trait.
+/// types of the [`Pattern`] trait.
 ///
 /// The trait is marked unsafe because the indices returned by the
-/// `next()` methods are required to lie on valid utf8 boundaries in
-/// the haystack. This enables consumers of this trait to
+/// [`next()`][Searcher::next] methods are required to lie on valid utf8
+/// boundaries in the haystack. This enables consumers of this trait to
 /// slice the haystack without additional runtime checks.
 pub unsafe trait Searcher<'a> {
     /// Getter for the underlying string to be searched in
     ///
-    /// Will always return the same `&str`
+    /// Will always return the same [`&str`][str].
     fn haystack(&self) -> &'a str;
 
     /// Performs the next search step starting from the front.
     ///
-    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
-    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
-    ///   pattern, even partially.
-    /// - Returns `Done` if every byte of the haystack has been visited
+    /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]` matches
+    ///   the pattern.
+    /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]` can
+    ///   not match the pattern, even partially.
+    /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack has
+    ///   been visited.
     ///
-    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// The stream of [`Match`][SearchStep::Match] and
+    /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
     /// will contain index ranges that are adjacent, non-overlapping,
     /// covering the whole haystack, and laying on utf8 boundaries.
     ///
-    /// A `Match` result needs to contain the whole matched pattern,
-    /// however `Reject` results may be split up into arbitrary
-    /// many adjacent fragments. Both ranges may have zero length.
+    /// A [`Match`][SearchStep::Match] result needs to contain the whole matched
+    /// pattern, however [`Reject`][SearchStep::Reject] results may be split up
+    /// into arbitrary many adjacent fragments. Both ranges may have zero length.
     ///
     /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
     /// might produce the stream
     /// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]`
     fn next(&mut self) -> SearchStep;
 
-    /// Finds the next `Match` result. See `next()`
+    /// Finds the next [`Match`][SearchStep::Match] result. See [`next()`][Searcher::next].
     ///
-    /// Unlike next(), there is no guarantee that the returned ranges
-    /// of this and next_reject will overlap. This will return (start_match, end_match),
-    /// where start_match is the index of where the match begins, and end_match is
-    /// the index after the end of the match.
+    /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
+    /// of this and [`next_reject`][Searcher::next_reject] will overlap. This will return
+    /// `(start_match, end_match)`, where start_match is the index of where
+    /// the match begins, and end_match is the index after the end of the match.
     #[inline]
     fn next_match(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -237,10 +231,11 @@ fn next_match(&mut self) -> Option<(usize, usize)> {
         }
     }
 
-    /// Finds the next `Reject` result. See `next()` and `next_match()`
+    /// Finds the next [`Reject`][SearchStep::Reject] result. See [`next()`][Searcher::next]
+    /// and [`next_match()`][Searcher::next_match].
     ///
-    /// Unlike next(), there is no guarantee that the returned ranges
-    /// of this and next_match will overlap.
+    /// Unlike [`next()`][Searcher::next], there is no guarantee that the returned ranges
+    /// of this and [`next_match`][Searcher::next_match] will overlap.
     #[inline]
     fn next_reject(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -258,37 +253,41 @@ fn next_reject(&mut self) -> Option<(usize, usize)> {
 /// This trait provides methods for searching for non-overlapping
 /// matches of a pattern starting from the back (right) of a string.
 ///
-/// It will be implemented by associated `Searcher`
-/// types of the `Pattern` trait if the pattern supports searching
+/// It will be implemented by associated [`Searcher`]
+/// types of the [`Pattern`] trait if the pattern supports searching
 /// for it from the back.
 ///
 /// The index ranges returned by this trait are not required
 /// to exactly match those of the forward search in reverse.
 ///
 /// For the reason why this trait is marked unsafe, see them
-/// parent trait `Searcher`.
+/// parent trait [`Searcher`].
 pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
     /// Performs the next search step starting from the back.
     ///
-    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
-    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
-    ///   pattern, even partially.
-    /// - Returns `Done` if every byte of the haystack has been visited
+    /// - Returns [`Match(a, b)`][SearchStep::Match] if `haystack[a..b]`
+    ///   matches the pattern.
+    /// - Returns [`Reject(a, b)`][SearchStep::Reject] if `haystack[a..b]`
+    ///   can not match the pattern, even partially.
+    /// - Returns [`Done`][SearchStep::Done] if every byte of the haystack
+    ///   has been visited
     ///
-    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// The stream of [`Match`][SearchStep::Match] and
+    /// [`Reject`][SearchStep::Reject] values up to a [`Done`][SearchStep::Done]
     /// will contain index ranges that are adjacent, non-overlapping,
     /// covering the whole haystack, and laying on utf8 boundaries.
     ///
-    /// A `Match` result needs to contain the whole matched pattern,
-    /// however `Reject` results may be split up into arbitrary
-    /// many adjacent fragments. Both ranges may have zero length.
+    /// A [`Match`][SearchStep::Match] result needs to contain the whole matched
+    /// pattern, however [`Reject`][SearchStep::Reject] results may be split up
+    /// into arbitrary many adjacent fragments. Both ranges may have zero length.
     ///
     /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
     /// might produce the stream
-    /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`
+    /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`.
     fn next_back(&mut self) -> SearchStep;
 
-    /// Finds the next `Match` result. See `next_back()`
+    /// Finds the next [`Match`][SearchStep::Match] result.
+    /// See [`next_back()`][ReverseSearcher::next_back].
     #[inline]
     fn next_match_back(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -300,7 +299,8 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
         }
     }
 
-    /// Finds the next `Reject` result. See `next_back()`
+    /// Finds the next [`Reject`][SearchStep::Reject] result.
+    /// See [`next_back()`][ReverseSearcher::next_back].
     #[inline]
     fn next_reject_back(&mut self) -> Option<(usize, usize)> {
         loop {
@@ -313,10 +313,10 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
     }
 }
 
-/// A marker trait to express that a `ReverseSearcher`
-/// can be used for a `DoubleEndedIterator` implementation.
+/// A marker trait to express that a [`ReverseSearcher`]
+/// can be used for a [`DoubleEndedIterator`] implementation.
 ///
-/// For this, the impl of `Searcher` and `ReverseSearcher` need
+/// For this, the impl of [`Searcher`] and [`ReverseSearcher`] need
 /// to follow these conditions:
 ///
 /// - All results of `next()` need to be identical
@@ -328,7 +328,7 @@ fn next_reject_back(&mut self) -> Option<(usize, usize)> {
 /// # Examples
 ///
 /// `char::Searcher` is a `DoubleEndedSearcher` because searching for a
-/// `char` only requires looking at one at a time, which behaves the same
+/// [`char`] only requires looking at one at a time, which behaves the same
 /// from both ends.
 ///
 /// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
@@ -355,13 +355,13 @@ pub struct CharSearcher<'a> {
     /// `finger_back` is the current byte index of the reverse search.
     /// Imagine that it exists after the byte at its index, i.e.
     /// haystack[finger_back - 1] is the last byte of the slice we must inspect during
-    /// forward searching (and thus the first byte to be inspected when calling next_back())
+    /// forward searching (and thus the first byte to be inspected when calling next_back()).
     finger_back: usize,
     /// The character being searched for
     needle: char,
 
     // safety invariant: `utf8_size` must be less than 5
-    /// The number of bytes `needle` takes up when encoded in utf8
+    /// The number of bytes `needle` takes up when encoded in utf8.
     utf8_size: usize,
     /// A utf8 encoded copy of the `needle`
     utf8_encoded: [u8; 4],
@@ -521,7 +521,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
 
 impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
 
-/// Searches for chars that are equal to a given `char`.
+/// Searches for chars that are equal to a given [`char`].
 ///
 /// # Examples
 ///
@@ -772,7 +772,7 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> {
 
 impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
 
-/// Searches for chars that are equal to any of the chars in the slice.
+/// Searches for chars that are equal to any of the [`char`]s in the slice.
 ///
 /// # Examples
 ///
@@ -821,7 +821,7 @@ unsafe impl<'a, F> ReverseSearcher<'a> for CharPredicateSearcher<'a, F>
 
 impl<'a, F> DoubleEndedSearcher<'a> for CharPredicateSearcher<'a, F> where F: FnMut(char) -> bool {}
 
-/// Searches for chars that match the given predicate.
+/// Searches for [`char`]s that match the given predicate.
 ///
 /// # Examples
 ///
index 286eb92915e49381a0dd1c42d870cfa28da28b6e..3943c66aad53a1ec9ecffd946c6c3401470bc7c7 100644 (file)
@@ -50,8 +50,9 @@
 /// handles is **not** available to raw handles returned from this function.
 ///
 /// The returned handle has no external synchronization or buffering.
-fn stdin_raw() -> io::Result<StdinRaw> {
-    stdio::Stdin::new().map(StdinRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stdin_raw() -> StdinRaw {
+    StdinRaw(stdio::Stdin::new())
 }
 
 /// Constructs a new raw handle to the standard output stream of this process.
@@ -63,8 +64,9 @@ fn stdin_raw() -> io::Result<StdinRaw> {
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stdout_raw() -> io::Result<StdoutRaw> {
-    stdio::Stdout::new().map(StdoutRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stdout_raw() -> StdoutRaw {
+    StdoutRaw(stdio::Stdout::new())
 }
 
 /// Constructs a new raw handle to the standard error stream of this process.
@@ -74,17 +76,18 @@ fn stdout_raw() -> io::Result<StdoutRaw> {
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-fn stderr_raw() -> io::Result<StderrRaw> {
-    stdio::Stderr::new().map(StderrRaw)
+#[unstable(feature = "libstd_sys_internals", issue = "none")]
+const fn stderr_raw() -> StderrRaw {
+    StderrRaw(stdio::Stderr::new())
 }
 
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
+        handle_ebadf(self.0.read(buf), 0)
     }
 
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
+        handle_ebadf(self.0.read_vectored(bufs), 0)
     }
 
     #[inline]
@@ -98,25 +101,22 @@ unsafe fn initializer(&self) -> Initializer {
     }
 
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        self.0.read_to_end(buf)
+        handle_ebadf(self.0.read_to_end(buf), 0)
     }
 
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        self.0.read_to_string(buf)
-    }
-
-    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        self.0.read_exact(buf)
+        handle_ebadf(self.0.read_to_string(buf), 0)
     }
 }
 
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
+        handle_ebadf(self.0.write(buf), buf.len())
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
+        let total = bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -125,29 +125,30 @@ fn is_write_vectored(&self) -> bool {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.0.flush()
+        handle_ebadf(self.0.flush(), ())
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.0.write_all(buf)
+        handle_ebadf(self.0.write_all(buf), ())
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        self.0.write_all_vectored(bufs)
+        handle_ebadf(self.0.write_all_vectored(bufs), ())
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.0.write_fmt(fmt)
+        handle_ebadf(self.0.write_fmt(fmt), ())
     }
 }
 
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
+        handle_ebadf(self.0.write(buf), buf.len())
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
+        let total = bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -156,80 +157,19 @@ fn is_write_vectored(&self) -> bool {
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        self.0.flush()
+        handle_ebadf(self.0.flush(), ())
     }
 
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.0.write_all(buf)
+        handle_ebadf(self.0.write_all(buf), ())
     }
 
     fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
-        self.0.write_all_vectored(bufs)
+        handle_ebadf(self.0.write_all_vectored(bufs), ())
     }
 
     fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
-        self.0.write_fmt(fmt)
-    }
-}
-
-enum Maybe<T> {
-    Real(T),
-    Fake,
-}
-
-impl<W: io::Write> io::Write for Maybe<W> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match *self {
-            Maybe::Real(ref mut w) => handle_ebadf(w.write(buf), buf.len()),
-            Maybe::Fake => Ok(buf.len()),
-        }
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = bufs.iter().map(|b| b.len()).sum();
-        match self {
-            Maybe::Real(w) => handle_ebadf(w.write_vectored(bufs), total),
-            Maybe::Fake => Ok(total),
-        }
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        match self {
-            Maybe::Real(w) => w.is_write_vectored(),
-            Maybe::Fake => true,
-        }
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        match *self {
-            Maybe::Real(ref mut w) => handle_ebadf(w.flush(), ()),
-            Maybe::Fake => Ok(()),
-        }
-    }
-}
-
-impl<R: io::Read> io::Read for Maybe<R> {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        match *self {
-            Maybe::Real(ref mut r) => handle_ebadf(r.read(buf), 0),
-            Maybe::Fake => Ok(0),
-        }
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self {
-            Maybe::Real(r) => handle_ebadf(r.read_vectored(bufs), 0),
-            Maybe::Fake => Ok(0),
-        }
-    }
-
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        match self {
-            Maybe::Real(w) => w.is_read_vectored(),
-            Maybe::Fake => true,
-        }
+        handle_ebadf(self.0.write_fmt(fmt), ())
     }
 }
 
@@ -274,7 +214,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdin {
-    inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
+    inner: Arc<Mutex<BufReader<StdinRaw>>>,
 }
 
 /// A locked reference to the `Stdin` handle.
@@ -305,7 +245,7 @@ pub struct Stdin {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdinLock<'a> {
-    inner: MutexGuard<'a, BufReader<Maybe<StdinRaw>>>,
+    inner: MutexGuard<'a, BufReader<StdinRaw>>,
 }
 
 /// Constructs a new handle to the standard input of the current process.
@@ -349,18 +289,14 @@ pub struct StdinLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
+    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = Lazy::new();
     return Stdin {
         inner: unsafe { INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") },
     };
 
-    fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
+    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
         // This must not reentrantly access `INSTANCE`
-        let stdin = match stdin_raw() {
-            Ok(stdin) => Maybe::Real(stdin),
-            _ => Maybe::Fake,
-        };
-
+        let stdin = stdin_raw();
         Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin)))
     }
 }
@@ -537,7 +473,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
+    inner: Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
 }
 
 /// A locked reference to the `Stdout` handle.
@@ -551,7 +487,7 @@ pub struct Stdout {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
+    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
 }
 
 /// Constructs a new handle to the standard output of the current process.
@@ -595,17 +531,14 @@ pub struct StdoutLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
-    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
+    static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = Lazy::new();
     return Stdout {
         inner: unsafe { INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") },
     };
 
-    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
+    fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> {
         // This must not reentrantly access `INSTANCE`
-        let stdout = match stdout_raw() {
-            Ok(stdout) => Maybe::Real(stdout),
-            _ => Maybe::Fake,
-        };
+        let stdout = stdout_raw();
         unsafe {
             let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
             ret.init();
@@ -715,7 +648,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: &'static ReentrantMutex<RefCell<Maybe<StderrRaw>>>,
+    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
 }
 
 /// A locked reference to the `Stderr` handle.
@@ -729,7 +662,7 @@ pub struct Stderr {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StderrLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<Maybe<StderrRaw>>>,
+    inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
 }
 
 /// Constructs a new handle to the standard error of the current process.
@@ -778,19 +711,14 @@ pub fn stderr() -> Stderr {
     //
     // This has the added benefit of allowing `stderr` to be usable during
     // process shutdown as well!
-    static INSTANCE: ReentrantMutex<RefCell<Maybe<StderrRaw>>> =
-        unsafe { ReentrantMutex::new(RefCell::new(Maybe::Fake)) };
+    static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
+        unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) };
 
     // When accessing stderr we need one-time initialization of the reentrant
-    // mutex, followed by one-time detection of whether we actually have a
-    // stderr handle or not. Afterwards we can just always use the now-filled-in
-    // `INSTANCE` value.
+    // mutex. Afterwards we can just always use the now-filled-in `INSTANCE` value.
     static INIT: Once = Once::new();
     INIT.call_once(|| unsafe {
         INSTANCE.init();
-        if let Ok(stderr) = stderr_raw() {
-            *INSTANCE.lock().borrow_mut() = Maybe::Real(stderr);
-        }
     });
     Stderr { inner: &INSTANCE }
 }
index 601563c5b1fcbdebe7e5dca84bea6f5432a42f61..7fec4731a462c6b89cb580e43de7e33a2624bf67 100644 (file)
@@ -6,8 +6,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -18,8 +18,8 @@ fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -37,8 +37,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -62,5 +62,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index f3654ee38716c7c54ab09e65f0230606465ba556..82304dd6dc2931112c1dedb7913204445f52d0cb 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 }
 
@@ -28,8 +28,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -69,8 +69,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -116,5 +116,5 @@ pub fn is_ebadf(_err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 716c174bd53b65a165231e2c1959603384b2a4d2..49f44f9f498aca1f55eadc62d39122ee346abe71 100644 (file)
@@ -19,8 +19,8 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -31,8 +31,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -47,8 +47,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
index f8353214cbca037fa635f342bf6e700a0aabf8e1..a05fe8165cff2f2bc5a2cebe9eff9837427ea5c5 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -28,8 +28,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -53,8 +53,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -84,5 +84,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 5a4e4505e93bddce1805a1f163e2df0c66bc7cfd..b5e3f5be9885bc7197bb651111b833cc244a8870 100644 (file)
@@ -5,8 +5,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 }
 
@@ -17,8 +17,8 @@ fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -33,8 +33,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
index 622444ccafd3cd0d97d4426b8e515951b82d1c77..92e9f205b4e6e2edaf2c7ac85c31f6bed2e00f88 100644 (file)
@@ -6,8 +6,8 @@
 pub struct Stderr(());
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin(()))
+    pub const fn new() -> Stdin {
+        Stdin(())
     }
 }
 
@@ -21,8 +21,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout(()))
+    pub const fn new() -> Stdout {
+        Stdout(())
     }
 }
 
@@ -40,8 +40,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr(()))
+    pub const fn new() -> Stderr {
+        Stderr(())
     }
 }
 
@@ -65,5 +65,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 78e3911dc4efea33e1edc322a40e54ab7856e2bb..23baafabf7933bd7ad116f0541a3466c687acb77 100644 (file)
@@ -7,8 +7,8 @@
 pub struct Stderr;
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin)
+    pub const fn new() -> Stdin {
+        Stdin
     }
 
     #[inline]
@@ -33,8 +33,8 @@ fn is_read_vectored(&self) -> bool {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 
     #[inline]
@@ -62,8 +62,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 
     #[inline]
@@ -98,5 +98,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index c84896296ecb930902e09d010d60c85d216c3c60..ff214497166beb8ac953c890312a5f5e29cb689f 100644 (file)
@@ -131,8 +131,8 @@ fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin { surrogate: 0 })
+    pub const fn new() -> Stdin {
+        Stdin { surrogate: 0 }
     }
 }
 
@@ -255,8 +255,8 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -271,8 +271,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -291,5 +291,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 5bdabf6d4b78efdaa81c74e514ce8076e459bf5e..872511af862a72d47ce767a0975fba1083600617 100644 (file)
@@ -30,8 +30,8 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
 }
 
 impl Stdin {
-    pub fn new() -> io::Result<Stdin> {
-        Ok(Stdin {})
+    pub const fn new() -> Stdin {
+        Stdin {}
     }
 }
 
@@ -44,8 +44,8 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 }
 
 impl Stdout {
-    pub fn new() -> io::Result<Stdout> {
-        Ok(Stdout)
+    pub const fn new() -> Stdout {
+        Stdout
     }
 }
 
@@ -60,8 +60,8 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 impl Stderr {
-    pub fn new() -> io::Result<Stderr> {
-        Ok(Stderr)
+    pub const fn new() -> Stderr {
+        Stderr
     }
 }
 
@@ -80,5 +80,5 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
-    Stderr::new().ok()
+    Some(Stderr::new())
 }
index 70b1c471ac3f0e6f11efc24d4d0b17a17a081354..8b8b01b11532731342b1413a0adcf86fb219252a 100644 (file)
@@ -527,7 +527,7 @@ pub fn parse(args: &[String]) -> Config {
 
         let build = toml.build.clone().unwrap_or_default();
         // set by bootstrap.py
-        config.hosts.push(config.build.clone());
+        config.hosts.push(config.build);
         for host in build.host.iter().map(|h| TargetSelection::from_user(h)) {
             if !config.hosts.contains(&host) {
                 config.hosts.push(host);
index a1b5ca2ea2fa1f18c128645704f1dd329c0e6d79..2a8f43950db3c2faab179cf77c9aeee5f68aefcd 100644 (file)
@@ -96,7 +96,7 @@ fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool {
         .paths
         .iter()
         .map(components_simplified)
-        .any(|requested| requested.iter().copied().eq(path.split("/")))
+        .any(|requested| requested.iter().copied().eq(path.split('/')))
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
index 56e4f0467cc50967978d2752e7cf99374e460977..38b3a32e3b5fbecd2dc01d9077145e9c0db10f13 100644 (file)
@@ -505,14 +505,11 @@ pub fn parse(args: &[String]) -> Flags {
 
         if let Subcommand::Check { .. } = &cmd {
             if matches.opt_str("stage").is_some() {
-                println!("{}", "--stage not supported for x.py check, always treated as stage 0");
+                println!("--stage not supported for x.py check, always treated as stage 0");
                 process::exit(1);
             }
             if matches.opt_str("keep-stage").is_some() {
-                println!(
-                    "{}",
-                    "--keep-stage not supported for x.py check, only one stage available"
-                );
+                println!("--keep-stage not supported for x.py check, only one stage available");
                 process::exit(1);
             }
         }
index 390b7e96b9a543cecdd806fe2369b10469bd9f50..6f93082e6752f01c559b572dcf85ff95873e8270 100644 (file)
@@ -87,7 +87,7 @@ pub fn format(build: &Build, check: bool) {
                 .lines()
                 .filter(|entry| entry.starts_with("??"))
                 .map(|entry| {
-                    entry.split(" ").nth(1).expect("every git status entry should list a path")
+                    entry.split(' ').nth(1).expect("every git status entry should list a path")
                 });
             for untracked_path in untracked_paths {
                 eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
index 77820ef87e3b470399217ffcbcb9c33128bcfe76..a42ee11bd6fe50df3f8dd0f8797b7ad17c39a54a 100644 (file)
@@ -323,10 +323,7 @@ pub enum Mode {
 
 impl Mode {
     pub fn is_tool(&self) -> bool {
-        match self {
-            Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => true,
-            _ => false,
-        }
+        matches!(self, Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd)
     }
 }
 
index eca9ddceae1b5a80c1b7424dfeca07b884e536bd..97d9dbdd63fb2f53809da3824b753c7f1fb74bd7 100644 (file)
@@ -767,7 +767,7 @@ fn supported_sanitizers(
 ) -> Vec<SanitizerRuntime> {
     let darwin_libs = |os: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
         components
-            .into_iter()
+            .iter()
             .map(move |c| SanitizerRuntime {
                 cmake_target: format!("clang_rt.{}_{}_dynamic", c, os),
                 path: out_dir
@@ -779,7 +779,7 @@ fn supported_sanitizers(
 
     let common_libs = |os: &str, arch: &str, components: &[&str]| -> Vec<SanitizerRuntime> {
         components
-            .into_iter()
+            .iter()
             .map(move |c| SanitizerRuntime {
                 cmake_target: format!("clang_rt.{}-{}", c, arch),
                 path: out_dir.join(&format!("build/lib/{}/libclang_rt.{}-{}.a", os, c, arch)),
index d16c2a9d0342c71f4512a02c4db1a1dab0d5abea..f45e22950643826ae87425146aceb7e597b92f8d 100644 (file)
@@ -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.
index 4115825e920838947ab4dee93124a1811980daaf..c43d91bf070edd97a878a9acdec8039fe954d4b1 100644 (file)
@@ -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
 
index a6062de6bf8af48a993668019c8ace8b3e994e1f..4fef94dde5f7a3f41dc60a31cceff88262bd3172 100644 (file)
@@ -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())
             }
index e6acc26ec2f343e6645755f6032eff88e8e385d3..b0209ac2899d616fd7e0fab082ea4b2915e5ed1c 100644 (file)
-#[cfg(test)]
-mod tests {
-    use crate::*;
-
-    fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
-        let s = &format!("r{}", s);
-        let mut cursor = Cursor::new(s);
-        cursor.bump();
-        let (n_hashes, err) = cursor.raw_double_quoted_string(0);
-        assert_eq!(n_hashes, expected_hashes);
-        assert_eq!(err, expected_err);
-    }
-
-    #[test]
-    fn test_naked_raw_str() {
-        check_raw_str(r#""abc""#, 0, None);
-    }
-
-    #[test]
-    fn test_raw_no_start() {
-        check_raw_str(r##""abc"#"##, 0, None);
-    }
-
-    #[test]
-    fn test_too_many_terminators() {
-        // this error is handled in the parser later
-        check_raw_str(r###"#"abc"##"###, 1, None);
-    }
-
-    #[test]
-    fn test_unterminated() {
-        check_raw_str(
-            r#"#"abc"#,
-            1,
-            Some(RawStrError::NoTerminator {
-                expected: 1,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        );
-        check_raw_str(
-            r###"##"abc"#"###,
-            2,
-            Some(RawStrError::NoTerminator {
-                expected: 2,
-                found: 1,
-                possible_terminator_offset: Some(7),
-            }),
-        );
-        // We're looking for "# not just any #
-        check_raw_str(
-            r###"##"abc#"###,
-            2,
-            Some(RawStrError::NoTerminator {
-                expected: 2,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        )
-    }
-
-    #[test]
-    fn test_invalid_start() {
-        check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
-    }
-
-    #[test]
-    fn test_unterminated_no_pound() {
-        // https://github.com/rust-lang/rust/issues/70677
-        check_raw_str(
-            r#"""#,
-            0,
-            Some(RawStrError::NoTerminator {
-                expected: 0,
-                found: 0,
-                possible_terminator_offset: None,
-            }),
-        );
-    }
-
-    #[test]
-    fn test_valid_shebang() {
-        // https://github.com/rust-lang/rust/issues/70528
-        let input = "#!/usr/bin/rustrun\nlet x = 5;";
-        assert_eq!(strip_shebang(input), Some(18));
-    }
-
-    #[test]
-    fn test_invalid_shebang_valid_rust_syntax() {
-        // https://github.com/rust-lang/rust/issues/70528
-        let input = "#!    [bad_attribute]";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_shebang_second_line() {
-        // Because shebangs are interpreted by the kernel, they must be on the first line
-        let input = "\n#!/bin/bash";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_shebang_space() {
-        let input = "#!    /bin/bash";
-        assert_eq!(strip_shebang(input), Some(input.len()));
-    }
-
-    #[test]
-    fn test_shebang_empty_shebang() {
-        let input = "#!    \n[attribute(foo)]";
-        assert_eq!(strip_shebang(input), None);
-    }
-
-    #[test]
-    fn test_invalid_shebang_comment() {
-        let input = "#!//bin/ami/a/comment\n[";
-        assert_eq!(strip_shebang(input), None)
-    }
-
-    #[test]
-    fn test_invalid_shebang_another_comment() {
-        let input = "#!/*bin/ami/a/comment*/\n[attribute";
-        assert_eq!(strip_shebang(input), None)
-    }
-
-    #[test]
-    fn test_shebang_valid_rust_after() {
-        let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
-        assert_eq!(strip_shebang(input), Some(23))
-    }
-
-    #[test]
-    fn test_shebang_followed_by_attrib() {
-        let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
-        assert_eq!(strip_shebang(input), Some(19));
-    }
+use super::*;
+
+fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
+    let s = &format!("r{}", s);
+    let mut cursor = Cursor::new(s);
+    cursor.bump();
+    let (n_hashes, err) = cursor.raw_double_quoted_string(0);
+    assert_eq!(n_hashes, expected_hashes);
+    assert_eq!(err, expected_err);
+}
+
+#[test]
+fn test_naked_raw_str() {
+    check_raw_str(r#""abc""#, 0, None);
+}
+
+#[test]
+fn test_raw_no_start() {
+    check_raw_str(r##""abc"#"##, 0, None);
+}
+
+#[test]
+fn test_too_many_terminators() {
+    // this error is handled in the parser later
+    check_raw_str(r###"#"abc"##"###, 1, None);
+}
+
+#[test]
+fn test_unterminated() {
+    check_raw_str(
+        r#"#"abc"#,
+        1,
+        Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
+    );
+    check_raw_str(
+        r###"##"abc"#"###,
+        2,
+        Some(RawStrError::NoTerminator {
+            expected: 2,
+            found: 1,
+            possible_terminator_offset: Some(7),
+        }),
+    );
+    // We're looking for "# not just any #
+    check_raw_str(
+        r###"##"abc#"###,
+        2,
+        Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
+    )
+}
+
+#[test]
+fn test_invalid_start() {
+    check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
+}
+
+#[test]
+fn test_unterminated_no_pound() {
+    // https://github.com/rust-lang/rust/issues/70677
+    check_raw_str(
+        r#"""#,
+        0,
+        Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
+    );
+}
+
+#[test]
+fn test_valid_shebang() {
+    // https://github.com/rust-lang/rust/issues/70528
+    let input = "#!/usr/bin/rustrun\nlet x = 5;";
+    assert_eq!(strip_shebang(input), Some(18));
+}
+
+#[test]
+fn test_invalid_shebang_valid_rust_syntax() {
+    // https://github.com/rust-lang/rust/issues/70528
+    let input = "#!    [bad_attribute]";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_shebang_second_line() {
+    // Because shebangs are interpreted by the kernel, they must be on the first line
+    let input = "\n#!/bin/bash";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_shebang_space() {
+    let input = "#!    /bin/bash";
+    assert_eq!(strip_shebang(input), Some(input.len()));
+}
+
+#[test]
+fn test_shebang_empty_shebang() {
+    let input = "#!    \n[attribute(foo)]";
+    assert_eq!(strip_shebang(input), None);
+}
+
+#[test]
+fn test_invalid_shebang_comment() {
+    let input = "#!//bin/ami/a/comment\n[";
+    assert_eq!(strip_shebang(input), None)
+}
+
+#[test]
+fn test_invalid_shebang_another_comment() {
+    let input = "#!/*bin/ami/a/comment*/\n[attribute";
+    assert_eq!(strip_shebang(input), None)
+}
+
+#[test]
+fn test_shebang_valid_rust_after() {
+    let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
+    assert_eq!(strip_shebang(input), Some(23))
+}
+
+#[test]
+fn test_shebang_followed_by_attrib() {
+    let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
+    assert_eq!(strip_shebang(input), Some(19));
 }
index e8fe3a97a10c76295c72d75cf7f1a87b7e3f7830..fcfd648c2b7aaaa97a182e2639715c05ed513bba 100644 (file)
@@ -103,7 +103,7 @@ pub enum TerminatorKind<'tcx> {
         unwind: Option<BasicBlock>,
     },
 
-    /// Block ends with a call of a converging function.
+    /// Block ends with a call of a function.
     Call {
         /// The function that’s being called.
         func: Operand<'tcx>,
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
deleted file mode 100644 (file)
index 86081b1..0000000
+++ /dev/null
@@ -1,3339 +0,0 @@
-// 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
-
-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_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::ErrorReported;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, FatalError};
-use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-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_target::spec::abi;
-use rustc_trait_selection::traits;
-use rustc_trait_selection::traits::astconv_object_safety_violations;
-use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
-use rustc_trait_selection::traits::wf::object_region_bounds;
-
-use smallvec::SmallVec;
-use std::collections::BTreeSet;
-use std::iter;
-use std::slice;
-
-#[derive(Debug)]
-pub struct PathSeg(pub DefId, pub usize);
-
-pub trait AstConv<'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
-    fn item_def_id(&self) -> Option<DefId>;
-
-    fn default_constness_for_trait_bounds(&self) -> Constness;
-
-    /// Returns predicates in scope of the form `X: Foo`, where `X` is
-    /// a type parameter `X` with the given id `def_id`. This is a
-    /// subset of the full set of predicates.
-    ///
-    /// This is used for one specific purpose: resolving "short-hand"
-    /// associated type references like `T::Item`. In principle, we
-    /// would do that by first getting the full set of predicates in
-    /// scope and then filtering down to find those that apply to `T`,
-    /// but this can lead to cycle errors. The problem is that we have
-    /// to do this resolution *in order to create the predicates in
-    /// the first place*. Hence, we have this "special pass".
-    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
-
-    /// Returns the lifetime to use when a lifetime is omitted (and not elided).
-    fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
-    -> Option<ty::Region<'tcx>>;
-
-    /// Returns the type to use when a type is omitted.
-    fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
-
-    /// Returns `true` if `_` is allowed in type signatures in the current context.
-    fn allow_ty_infer(&self) -> bool;
-
-    /// Returns the const to use when a const is omitted.
-    fn ct_infer(
-        &self,
-        ty: Ty<'tcx>,
-        param: Option<&ty::GenericParamDef>,
-        span: Span,
-    ) -> &'tcx Const<'tcx>;
-
-    /// Projecting an associated type from a (potentially)
-    /// higher-ranked trait reference is more complicated, because of
-    /// the possibility of late-bound regions appearing in the
-    /// associated type binding. This is not legal in function
-    /// signatures for that reason. In a function body, we can always
-    /// handle it because we can use inference variables to remove the
-    /// late-bound regions.
-    fn projected_ty_from_poly_trait_ref(
-        &self,
-        span: Span,
-        item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-        poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Ty<'tcx>;
-
-    /// Normalize an associated type coming from the user.
-    fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
-
-    /// Invoked when we encounter an error from some prior pass
-    /// (e.g., resolve) that is translated into a ty-error. This is
-    /// used to help suppress derived errors typeck might otherwise
-    /// report.
-    fn set_tainted_by_errors(&self);
-
-    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
-}
-
-pub enum SizedByDefault {
-    Yes,
-    No,
-}
-
-struct ConvertedBinding<'a, 'tcx> {
-    item_name: Ident,
-    kind: ConvertedBindingKind<'a, 'tcx>,
-    span: Span,
-}
-
-enum ConvertedBindingKind<'a, 'tcx> {
-    Equality(Ty<'tcx>),
-    Constraint(&'a [hir::GenericBound<'a>]),
-}
-
-/// New-typed boolean indicating whether explicit late-bound lifetimes
-/// are present in a set of generic arguments.
-///
-/// For example if we have some method `fn f<'a>(&'a self)` implemented
-/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
-/// is late-bound so should not be provided explicitly. Thus, if `f` is
-/// instantiated with some generic arguments providing `'a` explicitly,
-/// we taint those arguments with `ExplicitLateBound::Yes` so that we
-/// can provide an appropriate diagnostic later.
-#[derive(Copy, Clone, PartialEq)]
-pub enum ExplicitLateBound {
-    Yes,
-    No,
-}
-
-#[derive(Copy, Clone, PartialEq)]
-enum GenericArgPosition {
-    Type,
-    Value, // e.g., functions
-    MethodCall,
-}
-
-/// A marker denoting that the generic arguments that were
-/// provided did not match the respective generic parameters.
-#[derive(Clone, Default)]
-pub struct GenericArgCountMismatch {
-    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
-    pub reported: Option<ErrorReported>,
-    /// A list of spans of arguments provided that were not valid.
-    pub invalid_args: Vec<Span>,
-}
-
-/// Decorates the result of a generic argument count mismatch
-/// check with whether explicit late bounds were provided.
-#[derive(Clone)]
-pub struct GenericArgCountResult {
-    pub explicit_late_bound: ExplicitLateBound,
-    pub correct: Result<(), GenericArgCountMismatch>,
-}
-
-impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
-    pub fn ast_region_to_region(
-        &self,
-        lifetime: &hir::Lifetime,
-        def: Option<&ty::GenericParamDef>,
-    ) -> ty::Region<'tcx> {
-        let tcx = self.tcx();
-        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
-
-        let r = match tcx.named_region(lifetime.hir_id) {
-            Some(rl::Region::Static) => tcx.lifetimes.re_static,
-
-            Some(rl::Region::LateBound(debruijn, id, _)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(id, name)))
-            }
-
-            Some(rl::Region::LateBoundAnon(debruijn, index)) => {
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
-            }
-
-            Some(rl::Region::EarlyBound(index, id, _)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name }))
-            }
-
-            Some(rl::Region::Free(scope, id)) => {
-                let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReFree(ty::FreeRegion {
-                    scope,
-                    bound_region: ty::BrNamed(id, name),
-                }))
-
-                // (*) -- not late-bound, won't change
-            }
-
-            None => {
-                self.re_infer(def, lifetime.span).unwrap_or_else(|| {
-                    // This indicates an illegal lifetime
-                    // elision. `resolve_lifetime` should have
-                    // reported an error in this case -- but if
-                    // not, let's error out.
-                    tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
-
-                    // Supply some dummy value. We don't have an
-                    // `re_error`, annoyingly, so use `'static`.
-                    tcx.lifetimes.re_static
-                })
-            }
-        };
-
-        debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
-
-        r
-    }
-
-    /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
-    /// returns an appropriate set of substitutions for this particular reference to `I`.
-    pub fn ast_path_substs_for_ty(
-        &self,
-        span: Span,
-        def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> SubstsRef<'tcx> {
-        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
-            span,
-            def_id,
-            &[],
-            item_segment.generic_args(),
-            item_segment.infer_args,
-            None,
-        );
-
-        if let Some(b) = assoc_bindings.first() {
-            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
-        }
-
-        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::<Vec<_>>();
-
-            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<Span>,
-                                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<Span> = 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 `<T as Foo>::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<Ty<'tcx>>,
-        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(&param) = 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(&param) = 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(&param)) => {
-                        match (arg, &param.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::<Vec<(ParamKindOrd, GenericParamDef)>>();
-                                    param_types_present.sort_by_key(|(ord, _)| *ord);
-                                    let (mut param_types_present, ordered_params): (
-                                        Vec<ParamKindOrd>,
-                                        Vec<GenericParamDef>,
-                                    ) = 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::<Vec<String>>()
-                                                .join(", then "),
-                                            ordered_params
-                                                .into_iter()
-                                                .filter_map(|param| {
-                                                    if param.name == kw::SelfUpper {
-                                                        None
-                                                    } else {
-                                                        Some(param.name.to_string())
-                                                    }
-                                                })
-                                                .collect::<Vec<String>>()
-                                                .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(&param)) => {
-                        // 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.
-    /// Also returns back constraints on associated types.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// T: std::ops::Index<usize, Output = u32>
-    /// ^1 ^^^^^^^^^^^^^^2 ^^^^3  ^^^^^^^^^^^4
-    /// ```
-    ///
-    /// 1. The `self_ty` here would refer to the type `T`.
-    /// 2. The path in question is the path to the trait `std::ops::Index`,
-    ///    which will have been resolved to a `def_id`
-    /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
-    ///    parameters are returned in the `SubstsRef`, the associated type bindings like
-    ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
-    ///
-    /// Note that the type listing given here is *exactly* what the user provided.
-    ///
-    /// For (generic) associated types
-    ///
-    /// ```
-    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
-    /// ```
-    ///
-    /// We have the parent substs are the substs for the parent trait:
-    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
-    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
-    /// lists: `[Vec<u8>, u8, 'a]`.
-    fn create_substs_for_ast_path<'a>(
-        &self,
-        span: Span,
-        def_id: DefId,
-        parent_substs: &[subst::GenericArg<'tcx>],
-        generic_args: &'a hir::GenericArgs<'_>,
-        infer_args: bool,
-        self_ty: Option<Ty<'tcx>>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
-        // If the type is parameterized by this region, then replace this
-        // region with the current anon region binding (in other words,
-        // whatever & would get replaced with).
-        debug!(
-            "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
-                generic_args={:?})",
-            def_id, self_ty, generic_args
-        );
-
-        let tcx = self.tcx();
-        let generic_params = tcx.generics_of(def_id);
-
-        if generic_params.has_self {
-            if generic_params.parent.is_some() {
-                // The parent is a trait so it should have at least one subst
-                // for the `Self` type.
-                assert!(!parent_substs.is_empty())
-            } else {
-                // This item (presumably a trait) needs a self-type.
-                assert!(self_ty.is_some());
-            }
-        } else {
-            assert!(self_ty.is_none() && parent_substs.is_empty());
-        }
-
-        let arg_count = Self::check_generic_arg_count(
-            tcx,
-            span,
-            &generic_params,
-            &generic_args,
-            GenericArgPosition::Type,
-            self_ty.is_some(),
-            infer_args,
-        );
-
-        let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
-        let default_needs_object_self = |param: &ty::GenericParamDef| {
-            if let GenericParamDefKind::Type { has_default, .. } = param.kind {
-                if is_object && has_default {
-                    let default_ty = tcx.at(span).type_of(param.def_id);
-                    let self_param = tcx.types.self_param;
-                    if default_ty.walk().any(|arg| arg == self_param.into()) {
-                        // There is no suitable inference default for a type parameter
-                        // that references self, in an object type.
-                        return true;
-                    }
-                }
-            }
-
-            false
-        };
-
-        let mut missing_type_params = vec![];
-        let mut inferred_params = vec![];
-        let substs = Self::create_substs_for_generic_args(
-            tcx,
-            def_id,
-            parent_substs,
-            self_ty.is_some(),
-            self_ty,
-            arg_count.clone(),
-            // Provide the generic args, and whether types should be inferred.
-            |did| {
-                if did == def_id {
-                    (Some(generic_args), infer_args)
-                } else {
-                    // The last component of this tuple is unimportant.
-                    (None, false)
-                }
-            },
-            // Provide substitutions for parameters for which (valid) arguments have been provided.
-            |param, arg| match (&param.kind, arg) {
-                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
-                    self.ast_region_to_region(&lt, Some(param)).into()
-                }
-                (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
-                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
-                        inferred_params.push(ty.span);
-                        tcx.ty_error().into()
-                    } else {
-                        self.ast_ty_to_ty(&ty).into()
-                    }
-                }
-                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
-                    ty::Const::from_opt_const_arg_anon_const(
-                        tcx,
-                        ty::WithOptConstParam {
-                            did: tcx.hir().local_def_id(ct.value.hir_id),
-                            const_param_did: Some(param.def_id),
-                        },
-                    )
-                    .into()
-                }
-                _ => unreachable!(),
-            },
-            // Provide substitutions for parameters for which arguments are inferred.
-            |substs, param, infer_args| {
-                match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
-                    GenericParamDefKind::Type { has_default, .. } => {
-                        if !infer_args && has_default {
-                            // No type parameter provided, but a default exists.
-
-                            // If we are converting an object type, then the
-                            // `Self` parameter is unknown. However, some of the
-                            // other type parameters may reference `Self` in their
-                            // defaults. This will lead to an ICE if we are not
-                            // careful!
-                            if default_needs_object_self(param) {
-                                missing_type_params.push(param.name.to_string());
-                                tcx.ty_error().into()
-                            } else {
-                                // This is a default type parameter.
-                                self.normalize_ty(
-                                    span,
-                                    tcx.at(span).type_of(param.def_id).subst_spanned(
-                                        tcx,
-                                        substs.unwrap(),
-                                        Some(span),
-                                    ),
-                                )
-                                .into()
-                            }
-                        } else if infer_args {
-                            // No type parameters were provided, we can infer all.
-                            let param =
-                                if !default_needs_object_self(param) { Some(param) } else { None };
-                            self.ty_infer(param, span).into()
-                        } else {
-                            // We've already errored above about the mismatch.
-                            tcx.ty_error().into()
-                        }
-                    }
-                    GenericParamDefKind::Const => {
-                        let ty = tcx.at(span).type_of(param.def_id);
-                        // FIXME(const_generics:defaults)
-                        if infer_args {
-                            // No const parameters were provided, we can infer all.
-                            self.ct_infer(ty, Some(param), span).into()
-                        } else {
-                            // We've already errored above about the mismatch.
-                            tcx.const_error(ty).into()
-                        }
-                    }
-                }
-            },
-        );
-
-        self.complain_about_missing_type_params(
-            missing_type_params,
-            def_id,
-            span,
-            generic_args.args.is_empty(),
-        );
-
-        // Convert associated-type bindings or constraints into a separate vector.
-        // Example: Given this:
-        //
-        //     T: Iterator<Item = u32>
-        //
-        // The `T` is passed in as a self-type; the `Item = u32` is
-        // not a "type parameter" of the `Iterator` trait, but rather
-        // a restriction on `<T as Iterator>::Item`, so it is passed
-        // back separately.
-        let assoc_bindings = generic_args
-            .bindings
-            .iter()
-            .map(|binding| {
-                let kind = match binding.kind {
-                    hir::TypeBindingKind::Equality { ref ty } => {
-                        ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
-                    }
-                    hir::TypeBindingKind::Constraint { ref bounds } => {
-                        ConvertedBindingKind::Constraint(bounds)
-                    }
-                };
-                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
-            })
-            .collect();
-
-        debug!(
-            "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
-            generic_params, self_ty, substs
-        );
-
-        (substs, assoc_bindings, arg_count)
-    }
-
-    crate fn create_substs_for_associated_item(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        span: Span,
-        item_def_id: DefId,
-        item_segment: &hir::PathSegment<'_>,
-        parent_substs: SubstsRef<'tcx>,
-    ) -> SubstsRef<'tcx> {
-        if tcx.generics_of(item_def_id).params.is_empty() {
-            self.prohibit_generics(slice::from_ref(item_segment));
-
-            parent_substs
-        } else {
-            self.create_substs_for_ast_path(
-                span,
-                item_def_id,
-                parent_substs,
-                item_segment.generic_args(),
-                item_segment.infer_args,
-                None,
-            )
-            .0
-        }
-    }
-
-    /// 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<String>,
-        def_id: DefId,
-        span: Span,
-        empty_generic_args: bool,
-    ) {
-        if missing_type_params.is_empty() {
-            return;
-        }
-        let display =
-            missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
-        let mut err = struct_span_err!(
-            self.tcx().sess,
-            span,
-            E0393,
-            "the type parameter{} {} must be explicitly specified",
-            pluralize!(missing_type_params.len()),
-            display,
-        );
-        err.span_label(
-            self.tcx().def_span(def_id),
-            &format!(
-                "type parameter{} {} must be specified for this",
-                pluralize!(missing_type_params.len()),
-                display,
-            ),
-        );
-        let mut suggested = false;
-        if let (Ok(snippet), true) = (
-            self.tcx().sess.source_map().span_to_snippet(span),
-            // Don't suggest setting the type params if there are some already: the order is
-            // tricky to get right and the user will already know what the syntax is.
-            empty_generic_args,
-        ) {
-            if snippet.ends_with('>') {
-                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
-                // we would have to preserve the right order. For now, as clearly the user is
-                // aware of the syntax, we do nothing.
-            } else {
-                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                // least we can clue them to the correct syntax `Iterator<Type>`.
-                err.span_suggestion(
-                    span,
-                    &format!(
-                        "set the type parameter{plural} to the desired type{plural}",
-                        plural = pluralize!(missing_type_params.len()),
-                    ),
-                    format!("{}<{}>", snippet, missing_type_params.join(", ")),
-                    Applicability::HasPlaceholders,
-                );
-                suggested = true;
-            }
-        }
-        if !suggested {
-            err.span_label(
-                span,
-                format!(
-                    "missing reference{} to {}",
-                    pluralize!(missing_type_params.len()),
-                    display,
-                ),
-            );
-        }
-        err.note(
-            "because of the default `Self` reference, type parameters must be \
-                  specified on object types",
-        );
-        err.emit();
-    }
-
-    /// 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.
-    ///
-    /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>`
-    /// are disallowed. Otherwise, they are pushed onto the vector given.
-    pub fn instantiate_mono_trait_ref(
-        &self,
-        trait_ref: &hir::TraitRef<'_>,
-        self_ty: Ty<'tcx>,
-    ) -> ty::TraitRef<'tcx> {
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
-
-        self.ast_path_to_mono_trait_ref(
-            trait_ref.path.span,
-            trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
-            self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        )
-    }
-
-    /// The given trait-ref must actually be a trait.
-    pub(super) fn instantiate_poly_trait_ref_inner(
-        &self,
-        trait_ref: &hir::TraitRef<'_>,
-        span: Span,
-        constness: Constness,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-        speculative: bool,
-    ) -> GenericArgCountResult {
-        let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
-
-        debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
-
-        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
-
-        let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
-            trait_ref.path.span,
-            trait_def_id,
-            self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        );
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
-
-        bounds.trait_bounds.push((poly_trait_ref, span, constness));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in &assoc_bindings {
-            // Specify type to assert that error was already reported in `Err` case.
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                trait_ref.hir_ref_id,
-                poly_trait_ref,
-                binding,
-                bounds,
-                speculative,
-                &mut dup_bindings,
-                binding.span,
-            );
-            // Okay to ignore `Err` because of `ErrorReported` (see above).
-        }
-
-        debug!(
-            "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
-            trait_ref, bounds, poly_trait_ref
-        );
-
-        arg_count
-    }
-
-    /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
-    /// a full trait reference. The resulting trait reference is returned. This may also generate
-    /// auxiliary bounds, which are added to `bounds`.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// poly_trait_ref = Iterator<Item = u32>
-    /// self_ty = Foo
-    /// ```
-    ///
-    /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
-    ///
-    /// **A note on binders:** against our usual convention, there is an implied bounder around
-    /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
-    /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
-    /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
-    /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
-    /// however.
-    pub fn instantiate_poly_trait_ref(
-        &self,
-        poly_trait_ref: &hir::PolyTraitRef<'_>,
-        constness: Constness,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-    ) -> GenericArgCountResult {
-        self.instantiate_poly_trait_ref_inner(
-            &poly_trait_ref.trait_ref,
-            poly_trait_ref.span,
-            constness,
-            self_ty,
-            bounds,
-            false,
-        )
-    }
-
-    pub fn instantiate_lang_item_trait_ref(
-        &self,
-        lang_item: hir::LangItem,
-        span: Span,
-        hir_id: hir::HirId,
-        args: &GenericArgs<'_>,
-        self_ty: Ty<'tcx>,
-        bounds: &mut Bounds<'tcx>,
-    ) {
-        let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
-
-        let (substs, assoc_bindings, _) =
-            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
-        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
-        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in assoc_bindings {
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                hir_id,
-                poly_trait_ref,
-                &binding,
-                bounds,
-                false,
-                &mut dup_bindings,
-                span,
-            );
-        }
-    }
-
-    fn ast_path_to_mono_trait_ref(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        trait_segment: &hir::PathSegment<'_>,
-    ) -> ty::TraitRef<'tcx> {
-        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);
-        }
-        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::<Result<Vec<_>, _>>()
-                                        .map(|a| a.join(", ")),
-                                    _ => sess.source_map().span_to_snippet(ty.span),
-                                }
-                                .map(|s| format!("({})", s))
-                                .ok(),
-                                _ => None,
-                            })
-                            .unwrap_or_else(|| "()".to_string()),
-                        trait_segment
-                            .generic_args()
-                            .bindings
-                            .iter()
-                            .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
-                                (true, hir::TypeBindingKind::Equality { ty }) => {
-                                    sess.source_map().span_to_snippet(ty.span).ok()
-                                }
-                                _ => None,
-                            })
-                            .unwrap_or_else(|| "()".to_string()),
-                    )),
-                )
-            } else {
-                ("parenthetical notation is only stable when used with `Fn`-family traits", None)
-            };
-            let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
-            if let Some(sugg) = sugg {
-                let msg = "use parenthetical notation instead";
-                err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
-            }
-            err.emit();
-        }
-    }
-
-    fn create_substs_for_ast_trait_ref<'a>(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        trait_segment: &'a hir::PathSegment<'a>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
-        debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
-
-        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
-
-        self.create_substs_for_ast_path(
-            span,
-            trait_def_id,
-            &[],
-            trait_segment.generic_args(),
-            trait_segment.infer_args,
-            Some(self_ty),
-        )
-    }
-
-    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
-        self.tcx()
-            .associated_items(trait_def_id)
-            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
-            .is_some()
-    }
-
-    // Returns `true` if a bounds list includes `?Sized`.
-    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
-        let tcx = self.tcx();
-
-        // Try to find an unbound in bounds.
-        let mut unbound = None;
-        for ab in ast_bounds {
-            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
-                if unbound.is_none() {
-                    unbound = Some(&ptr.trait_ref);
-                } else {
-                    struct_span_err!(
-                        tcx.sess,
-                        span,
-                        E0203,
-                        "type parameter has more than one relaxed default \
-                        bound, only one is supported"
-                    )
-                    .emit();
-                }
-            }
-        }
-
-        let kind_id = tcx.lang_items().require(SizedTraitLangItem);
-        match unbound {
-            Some(tpb) => {
-                // FIXME(#8559) currently requires the unbound to be built-in.
-                if let Ok(kind_id) = kind_id {
-                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
-                        tcx.sess.span_warn(
-                            span,
-                            "default bound relaxed for a type parameter, but \
-                             this does nothing because the given bound is not \
-                             a default; only `?Sized` is supported",
-                        );
-                    }
-                }
-            }
-            _ if kind_id.is_ok() => {
-                return false;
-            }
-            // No lang item for `Sized`, so we can't add it as a bound.
-            None => {}
-        }
-
-        true
-    }
-
-    /// This helper takes a *converted* parameter type (`param_ty`)
-    /// and an *unconverted* list of bounds:
-    ///
-    /// ```text
-    /// fn foo<T: Debug>
-    ///        ^  ^^^^^ `ast_bounds` parameter, in HIR form
-    ///        |
-    ///        `param_ty`, in ty form
-    /// ```
-    ///
-    /// It adds these `ast_bounds` into the `bounds` structure.
-    ///
-    /// **A note on binders:** there is an implied binder around
-    /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
-    /// for more details.
-    fn add_bounds(
-        &self,
-        param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
-        bounds: &mut Bounds<'tcx>,
-    ) {
-        let mut trait_bounds = Vec::new();
-        let mut region_bounds = Vec::new();
-
-        let constness = self.default_constness_for_trait_bounds();
-        for ast_bound in ast_bounds {
-            match *ast_bound {
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
-                    trait_bounds.push((b, constness))
-                }
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
-                    trait_bounds.push((b, Constness::NotConst))
-                }
-                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
-                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
-                    .instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
-                    ),
-                hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
-            }
-        }
-
-        for (bound, constness) in trait_bounds {
-            let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
-        }
-
-        bounds.region_bounds.extend(
-            region_bounds.into_iter().map(|r| (self.ast_region_to_region(r, None), r.span)),
-        );
-    }
-
-    /// Translates a list of bounds from the HIR into the `Bounds` data structure.
-    /// The self-type for the bounds is given by `param_ty`.
-    ///
-    /// Example:
-    ///
-    /// ```
-    /// fn foo<T: Bar + Baz>() { }
-    ///        ^  ^^^^^^^^^ ast_bounds
-    ///        param_ty
-    /// ```
-    ///
-    /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
-    /// considered `Sized` unless there is an explicit `?Sized` bound.  This would be true in the
-    /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
-    ///
-    /// `span` should be the declaration size of the parameter.
-    pub fn compute_bounds(
-        &self,
-        param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
-    ) -> Bounds<'tcx> {
-        let mut bounds = Bounds::default();
-
-        self.add_bounds(param_ty, ast_bounds, &mut bounds);
-        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
-
-        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
-            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
-        } else {
-            None
-        };
-
-        bounds
-    }
-
-    /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
-    /// onto `bounds`.
-    ///
-    /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
-    /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
-    /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
-    fn add_predicates_for_ast_type_binding(
-        &self,
-        hir_ref_id: hir::HirId,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        binding: &ConvertedBinding<'_, 'tcx>,
-        bounds: &mut Bounds<'tcx>,
-        speculative: bool,
-        dup_bindings: &mut FxHashMap<DefId, Span>,
-        path_span: Span,
-    ) -> Result<(), ErrorReported> {
-        let tcx = self.tcx();
-
-        if !speculative {
-            // Given something like `U: SomeTrait<T = X>`, we want to produce a
-            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
-            // subtle in the event that `T` is defined in a supertrait of
-            // `SomeTrait`, because in that case we need to upcast.
-            //
-            // That is, consider this case:
-            //
-            // ```
-            // trait SubTrait: SuperTrait<i32> { }
-            // trait SuperTrait<A> { type T; }
-            //
-            // ... B: SubTrait<T = foo> ...
-            // ```
-            //
-            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
-
-            // Find any late-bound regions declared in `ty` that are not
-            // declared in the trait-ref. These are not well-formed.
-            //
-            // Example:
-            //
-            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
-            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
-            if let ConvertedBindingKind::Equality(ty) = binding.kind {
-                let late_bound_in_trait_ref =
-                    tcx.collect_constrained_late_bound_regions(&trait_ref);
-                let late_bound_in_ty =
-                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
-                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
-                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
-
-                // FIXME: point at the type params that don't have appropriate lifetimes:
-                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
-                //                         ----  ----     ^^^^^^^
-                self.validate_late_bound_regions(
-                    late_bound_in_trait_ref,
-                    late_bound_in_ty,
-                    |br_name| {
-                        struct_span_err!(
-                            tcx.sess,
-                            binding.span,
-                            E0582,
-                            "binding for associated type `{}` references {}, \
-                             which does not appear in the trait input types",
-                            binding.item_name,
-                            br_name
-                        )
-                    },
-                );
-            }
-        }
-
-        let candidate =
-            if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
-                // Simple case: X is defined in the current trait.
-                trait_ref
-            } else {
-                // Otherwise, we have to walk through the supertraits to find
-                // those that do.
-                self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, trait_ref),
-                    || trait_ref.print_only_trait_path().to_string(),
-                    binding.item_name,
-                    path_span,
-                    || match binding.kind {
-                        ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
-                        _ => None,
-                    },
-                )?
-            };
-
-        let (assoc_ident, def_scope) =
-            tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
-
-        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
-        // of calling `filter_by_name_and_kind`.
-        let assoc_ty = tcx
-            .associated_items(candidate.def_id())
-            .filter_by_name_unhygienic(assoc_ident.name)
-            .find(|i| {
-                i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident
-            })
-            .expect("missing associated type");
-
-        if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
-            tcx.sess
-                .struct_span_err(
-                    binding.span,
-                    &format!("associated type `{}` is private", binding.item_name),
-                )
-                .span_label(binding.span, "private associated type")
-                .emit();
-        }
-        tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span);
-
-        if !speculative {
-            dup_bindings
-                .entry(assoc_ty.def_id)
-                .and_modify(|prev_span| {
-                    struct_span_err!(
-                        self.tcx().sess,
-                        binding.span,
-                        E0719,
-                        "the value of the associated type `{}` (from trait `{}`) \
-                         is already specified",
-                        binding.item_name,
-                        tcx.def_path_str(assoc_ty.container.id())
-                    )
-                    .span_label(binding.span, "re-bound here")
-                    .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
-                    .emit();
-                })
-                .or_insert(binding.span);
-        }
-
-        match binding.kind {
-            ConvertedBindingKind::Equality(ref ty) => {
-                // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
-                // the "projection predicate" for:
-                //
-                // `<T as Iterator>::Item = u32`
-                bounds.projection_bounds.push((
-                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy::from_ref_and_name(
-                            tcx,
-                            trait_ref,
-                            binding.item_name,
-                        ),
-                        ty,
-                    }),
-                    binding.span,
-                ));
-            }
-            ConvertedBindingKind::Constraint(ast_bounds) => {
-                // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
-                //
-                // `<T as Iterator>::Item: Debug`
-                //
-                // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
-                // parameter to have a skipped binder.
-                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
-                self.add_bounds(param_ty, ast_bounds, bounds);
-            }
-        }
-        Ok(())
-    }
-
-    fn ast_path_to_ty(
-        &self,
-        span: Span,
-        did: DefId,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> Ty<'tcx> {
-        let substs = self.ast_path_substs_for_ty(span, did, item_segment);
-        self.normalize_ty(span, self.tcx().at(span).type_of(did).subst(self.tcx(), substs))
-    }
-
-    fn conv_object_ty_poly_trait_ref(
-        &self,
-        span: Span,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
-        lifetime: &hir::Lifetime,
-        borrowed: bool,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        let mut bounds = Bounds::default();
-        let mut potential_assoc_types = Vec::new();
-        let dummy_self = self.tcx().types.trait_object_dummy_self;
-        for trait_bound in trait_bounds.iter().rev() {
-            if let GenericArgCountResult {
-                correct:
-                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
-                ..
-            } = self.instantiate_poly_trait_ref(
-                trait_bound,
-                Constness::NotConst,
-                dummy_self,
-                &mut bounds,
-            ) {
-                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
-            }
-        }
-
-        // Expand trait aliases recursively and check that only one regular (non-auto) trait
-        // is used and no 'maybe' bounds are used.
-        let expanded_traits =
-            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
-        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
-            expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
-        if regular_traits.len() > 1 {
-            let first_trait = &regular_traits[0];
-            let additional_trait = &regular_traits[1];
-            let mut err = struct_span_err!(
-                tcx.sess,
-                additional_trait.bottom().1,
-                E0225,
-                "only auto traits can be used as additional traits in a trait object"
-            );
-            additional_trait.label_with_exp_info(
-                &mut err,
-                "additional non-auto trait",
-                "additional use",
-            );
-            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
-            err.help(&format!(
-                "consider creating a new trait with all of these as super-traits and using that \
-                 trait here instead: `trait NewTrait: {} {{}}`",
-                regular_traits
-                    .iter()
-                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
-                    .collect::<Vec<_>>()
-                    .join(" + "),
-            ));
-            err.note(
-                "auto-traits like `Send` and `Sync` are traits that have special properties; \
-                 for more information on them, visit \
-                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
-            );
-            err.emit();
-        }
-
-        if regular_traits.is_empty() && auto_traits.is_empty() {
-            struct_span_err!(
-                tcx.sess,
-                span,
-                E0224,
-                "at least one trait is required for an object type"
-            )
-            .emit();
-            return tcx.ty_error();
-        }
-
-        // Check that there are no gross object safety violations;
-        // most importantly, that the supertraits don't contain `Self`,
-        // to avoid ICEs.
-        for item in &regular_traits {
-            let object_safety_violations =
-                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
-            if !object_safety_violations.is_empty() {
-                report_object_safety_error(
-                    tcx,
-                    span,
-                    item.trait_ref().def_id(),
-                    &object_safety_violations[..],
-                )
-                .emit();
-                return tcx.ty_error();
-            }
-        }
-
-        // Use a `BTreeSet` to keep output in a more consistent order.
-        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
-
-        let regular_traits_refs_spans = bounds
-            .trait_bounds
-            .into_iter()
-            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
-
-        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
-            assert_eq!(constness, Constness::NotConst);
-
-            for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
-                debug!(
-                    "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
-                    obligation.predicate
-                );
-
-                match obligation.predicate.skip_binders() {
-                    ty::PredicateAtom::Trait(pred, _) => {
-                        let pred = ty::Binder::bind(pred);
-                        associated_types.entry(span).or_default().extend(
-                            tcx.associated_items(pred.def_id())
-                                .in_definition_order()
-                                .filter(|item| item.kind == ty::AssocKind::Type)
-                                .map(|item| item.def_id),
-                        );
-                    }
-                    ty::PredicateAtom::Projection(pred) => {
-                        let pred = ty::Binder::bind(pred);
-                        // A `Self` within the original bound will be substituted with a
-                        // `trait_object_dummy_self`, so check for that.
-                        let references_self =
-                            pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
-
-                        // If the projection output contains `Self`, force the user to
-                        // elaborate it explicitly to avoid a lot of complexity.
-                        //
-                        // The "classicaly useful" case is the following:
-                        // ```
-                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
-                        //         type MyOutput;
-                        //     }
-                        // ```
-                        //
-                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
-                        // but actually supporting that would "expand" to an infinitely-long type
-                        // `fix $ Ï„ â†’ dyn MyTrait<MyOutput = X, Output = <Ï„ as MyTrait>::MyOutput`.
-                        //
-                        // Instead, we force the user to write
-                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
-                        // the discussion in #56288 for alternatives.
-                        if !references_self {
-                            // Include projections defined on supertraits.
-                            bounds.projection_bounds.push((pred, span));
-                        }
-                    }
-                    _ => (),
-                }
-            }
-        }
-
-        for (projection_bound, _) in &bounds.projection_bounds {
-            for def_ids in associated_types.values_mut() {
-                def_ids.remove(&projection_bound.projection_def_id());
-            }
-        }
-
-        self.complain_about_missing_associated_types(
-            associated_types,
-            potential_assoc_types,
-            trait_bounds,
-        );
-
-        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
-        // `dyn Trait + Send`.
-        auto_traits.sort_by_key(|i| i.trait_ref().def_id());
-        auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
-        debug!("regular_traits: {:?}", regular_traits);
-        debug!("auto_traits: {:?}", auto_traits);
-
-        // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
-        // removing the dummy `Self` type (`trait_object_dummy_self`).
-        let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
-            if trait_ref.self_ty() != dummy_self {
-                // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
-                // which picks up non-supertraits where clauses - but also, the object safety
-                // completely ignores trait aliases, which could be object safety hazards. We
-                // `delay_span_bug` here to avoid an ICE in stable even when the feature is
-                // disabled. (#66420)
-                tcx.sess.delay_span_bug(
-                    DUMMY_SP,
-                    &format!(
-                        "trait_ref_to_existential called on {:?} with non-dummy Self",
-                        trait_ref,
-                    ),
-                );
-            }
-            ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
-        };
-
-        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
-        let existential_trait_refs =
-            regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential));
-        let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|b| {
-                let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
-                ty::ExistentialProjection {
-                    ty: b.ty,
-                    item_def_id: b.projection_ty.item_def_id,
-                    substs: trait_ref.substs,
-                }
-            })
-        });
-
-        // Calling `skip_binder` is okay because the predicates are re-bound.
-        let regular_trait_predicates = existential_trait_refs
-            .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
-        let auto_trait_predicates = auto_traits
-            .into_iter()
-            .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
-        let mut v = regular_trait_predicates
-            .chain(auto_trait_predicates)
-            .chain(
-                existential_projections
-                    .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
-            )
-            .collect::<SmallVec<[_; 8]>>();
-        v.sort_by(|a, b| a.stable_cmp(tcx, b));
-        v.dedup();
-        let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
-
-        // Use explicitly-specified region bound.
-        let region_bound = if !lifetime.is_elided() {
-            self.ast_region_to_region(lifetime, None)
-        } else {
-            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_region(lifetime.hir_id).is_some() {
-                    self.ast_region_to_region(lifetime, None)
-                } else {
-                    self.re_infer(None, span).unwrap_or_else(|| {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0228,
-                            "the lifetime bound for this object type cannot be deduced \
-                             from context; please supply an explicit bound"
-                        );
-                        if borrowed {
-                            // We will have already emitted an error E0106 complaining about a
-                            // missing named lifetime in `&dyn Trait`, so we elide this one.
-                            err.delay_as_bug();
-                        } else {
-                            err.emit();
-                        }
-                        tcx.lifetimes.re_static
-                    })
-                }
-            })
-        };
-        debug!("region_bound: {:?}", region_bound);
-
-        let ty = tcx.mk_dynamic(existential_predicates, region_bound);
-        debug!("trait_object_type: {:?}", ty);
-        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<Span, BTreeSet<DefId>>,
-        potential_assoc_types: Vec<Span>,
-        trait_bounds: &[hir::PolyTraitRef<'_>],
-    ) {
-        if associated_types.values().all(|v| v.is_empty()) {
-            return;
-        }
-        let tcx = self.tcx();
-        // FIXME: Marked `mut` so that we can replace the spans further below with a more
-        // appropriate one, but this should be handled earlier in the span assignment.
-        let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
-            .into_iter()
-            .map(|(span, def_ids)| {
-                (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
-            })
-            .collect();
-        let mut names = vec![];
-
-        // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
-        // `issue-22560.rs`.
-        let mut trait_bound_spans: Vec<Span> = vec![];
-        for (span, items) in &associated_types {
-            if !items.is_empty() {
-                trait_bound_spans.push(*span);
-            }
-            for assoc_item in items {
-                let trait_def_id = assoc_item.container.id();
-                names.push(format!(
-                    "`{}` (from trait `{}`)",
-                    assoc_item.ident,
-                    tcx.def_path_str(trait_def_id),
-                ));
-            }
-        }
-        if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
-            match &bound.trait_ref.path.segments[..] {
-                // FIXME: `trait_ref.path.span` can point to a full path with multiple
-                // segments, even though `trait_ref.path.segments` is of length `1`. Work
-                // around that bug here, even though it should be fixed elsewhere.
-                // This would otherwise cause an invalid suggestion. For an example, look at
-                // `src/test/ui/issues/issue-28344.rs` where instead of the following:
-                //
-                //   error[E0191]: the value of the associated type `Output`
-                //                 (from trait `std::ops::BitXor`) must be specified
-                //   --> $DIR/issue-28344.rs:4:17
-                //    |
-                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-                //    |                 ^^^^^^ help: specify the associated type:
-                //    |                              `BitXor<Output = Type>`
-                //
-                // we would output:
-                //
-                //   error[E0191]: the value of the associated type `Output`
-                //                 (from trait `std::ops::BitXor`) must be specified
-                //   --> $DIR/issue-28344.rs:4:17
-                //    |
-                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-                //    |                 ^^^^^^^^^^^^^ help: specify the associated type:
-                //    |                                     `BitXor::bitor<Output = Type>`
-                [segment] if segment.args.is_none() => {
-                    trait_bound_spans = vec![segment.ident.span];
-                    associated_types = associated_types
-                        .into_iter()
-                        .map(|(_, items)| (segment.ident.span, items))
-                        .collect();
-                }
-                _ => {}
-            }
-        }
-        names.sort();
-        trait_bound_spans.sort();
-        let mut err = struct_span_err!(
-            tcx.sess,
-            trait_bound_spans,
-            E0191,
-            "the value of the associated type{} {} must be specified",
-            pluralize!(names.len()),
-            names.join(", "),
-        );
-        let mut suggestions = vec![];
-        let mut types_count = 0;
-        let mut where_constraints = vec![];
-        for (span, assoc_items) in &associated_types {
-            let mut names: FxHashMap<_, usize> = FxHashMap::default();
-            for item in assoc_items {
-                types_count += 1;
-                *names.entry(item.ident.name).or_insert(0) += 1;
-            }
-            let mut dupes = false;
-            for item in assoc_items {
-                let prefix = if names[&item.ident.name] > 1 {
-                    let trait_def_id = item.container.id();
-                    dupes = true;
-                    format!("{}::", tcx.def_path_str(trait_def_id))
-                } else {
-                    String::new()
-                };
-                if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
-                    err.span_label(sp, format!("`{}{}` defined here", prefix, item.ident));
-                }
-            }
-            if potential_assoc_types.len() == assoc_items.len() {
-                // Only suggest when the amount of missing associated types equals the number of
-                // extra type arguments present, as that gives us a relatively high confidence
-                // that the user forgot to give the associtated type's name. The canonical
-                // example would be trying to use `Iterator<isize>` instead of
-                // `Iterator<Item = isize>`.
-                for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) {
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
-                        suggestions.push((*potential, format!("{} = {}", item.ident, snippet)));
-                    }
-                }
-            } else if let (Ok(snippet), false) =
-                (tcx.sess.source_map().span_to_snippet(*span), dupes)
-            {
-                let types: Vec<_> =
-                    assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect();
-                let code = if snippet.ends_with('>') {
-                    // The user wrote `Trait<'a>` or similar and we don't have a type we can
-                    // suggest, but at least we can clue them to the correct syntax
-                    // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
-                    // suggestion.
-                    format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
-                } else {
-                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                    // least we can clue them to the correct syntax `Iterator<Item = Type>`.
-                    format!("{}<{}>", snippet, types.join(", "))
-                };
-                suggestions.push((*span, code));
-            } else if dupes {
-                where_constraints.push(*span);
-            }
-        }
-        let where_msg = "consider introducing a new type parameter, adding `where` constraints \
-                         using the fully-qualified path to the associated types";
-        if !where_constraints.is_empty() && suggestions.is_empty() {
-            // If there are duplicates associated type names and a single trait bound do not
-            // use structured suggestion, it means that there are multiple super-traits with
-            // the same associated type name.
-            err.help(where_msg);
-        }
-        if suggestions.len() != 1 {
-            // We don't need this label if there's an inline suggestion, show otherwise.
-            for (span, assoc_items) in &associated_types {
-                let mut names: FxHashMap<_, usize> = FxHashMap::default();
-                for item in assoc_items {
-                    types_count += 1;
-                    *names.entry(item.ident.name).or_insert(0) += 1;
-                }
-                let mut label = vec![];
-                for item in assoc_items {
-                    let postfix = if names[&item.ident.name] > 1 {
-                        let trait_def_id = item.container.id();
-                        format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
-                    } else {
-                        String::new()
-                    };
-                    label.push(format!("`{}`{}", item.ident, postfix));
-                }
-                if !label.is_empty() {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "associated type{} {} must be specified",
-                            pluralize!(label.len()),
-                            label.join(", "),
-                        ),
-                    );
-                }
-            }
-        }
-        if !suggestions.is_empty() {
-            err.multipart_suggestion(
-                &format!("specify the associated type{}", pluralize!(types_count)),
-                suggestions,
-                Applicability::HasPlaceholders,
-            );
-            if !where_constraints.is_empty() {
-                err.span_help(where_constraints, where_msg);
-            }
-        }
-        err.emit();
-    }
-
-    fn report_ambiguous_associated_type(
-        &self,
-        span: Span,
-        type_str: &str,
-        trait_str: &str,
-        name: Symbol,
-    ) {
-        let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
-        if let (Some(_), Ok(snippet)) = (
-            self.tcx().sess.confused_type_with_std_module.borrow().get(&span),
-            self.tcx().sess.source_map().span_to_snippet(span),
-        ) {
-            err.span_suggestion(
-                span,
-                "you are looking for the module in `std`, not the primitive type",
-                format!("std::{}", snippet),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            err.span_suggestion(
-                span,
-                "use fully-qualified syntax",
-                format!("<{} as {}>::{}", type_str, trait_str, name),
-                Applicability::HasPlaceholders,
-            );
-        }
-        err.emit();
-    }
-
-    // Search for a bound on a type parameter which includes the associated item
-    // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
-    // This function will fail if there are no suitable bounds or there is
-    // any ambiguity.
-    fn find_bound_for_assoc_item(
-        &self,
-        ty_param_def_id: LocalDefId,
-        assoc_name: Ident,
-        span: Span,
-    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported> {
-        let tcx = self.tcx();
-
-        debug!(
-            "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
-            ty_param_def_id, assoc_name, span,
-        );
-
-        let predicates =
-            &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
-
-        debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
-
-        let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
-        let param_name = tcx.hir().ty_param_name(param_hir_id);
-        self.one_bound_for_assoc_type(
-            || {
-                traits::transitive_bounds(
-                    tcx,
-                    predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
-                )
-            },
-            || param_name.to_string(),
-            assoc_name,
-            span,
-            || None,
-        )
-    }
-
-    // Checks that `bounds` contains exactly one element and reports appropriate
-    // errors otherwise.
-    fn one_bound_for_assoc_type<I>(
-        &self,
-        all_candidates: impl Fn() -> I,
-        ty_param_name: impl Fn() -> String,
-        assoc_name: Ident,
-        span: Span,
-        is_equality: impl Fn() -> Option<String>,
-    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
-    where
-        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
-    {
-        let mut matching_candidates = all_candidates()
-            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
-
-        let bound = match matching_candidates.next() {
-            Some(bound) => bound,
-            None => {
-                self.complain_about_assoc_type_not_found(
-                    all_candidates,
-                    &ty_param_name(),
-                    assoc_name,
-                    span,
-                );
-                return Err(ErrorReported);
-            }
-        };
-
-        debug!("one_bound_for_assoc_type: bound = {:?}", bound);
-
-        if let Some(bound2) = matching_candidates.next() {
-            debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
-
-            let is_equality = is_equality();
-            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
-            let mut err = if is_equality.is_some() {
-                // More specific Error Index entry.
-                struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0222,
-                    "ambiguous associated type `{}` in bounds of `{}`",
-                    assoc_name,
-                    ty_param_name()
-                )
-            } else {
-                struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0221,
-                    "ambiguous associated type `{}` in bounds of `{}`",
-                    assoc_name,
-                    ty_param_name()
-                )
-            };
-            err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
-
-            let mut where_bounds = vec![];
-            for bound in bounds {
-                let bound_id = bound.def_id();
-                let bound_span = self
-                    .tcx()
-                    .associated_items(bound_id)
-                    .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
-                    .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
-
-                if let Some(bound_span) = bound_span {
-                    err.span_label(
-                        bound_span,
-                        format!(
-                            "ambiguous `{}` from `{}`",
-                            assoc_name,
-                            bound.print_only_trait_path(),
-                        ),
-                    );
-                    if let Some(constraint) = &is_equality {
-                        where_bounds.push(format!(
-                            "        T: {trait}::{assoc} = {constraint}",
-                            trait=bound.print_only_trait_path(),
-                            assoc=assoc_name,
-                            constraint=constraint,
-                        ));
-                    } else {
-                        err.span_suggestion(
-                            span,
-                            "use fully qualified syntax to disambiguate",
-                            format!(
-                                "<{} as {}>::{}",
-                                ty_param_name(),
-                                bound.print_only_trait_path(),
-                                assoc_name,
-                            ),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                } else {
-                    err.note(&format!(
-                        "associated type `{}` could derive from `{}`",
-                        ty_param_name(),
-                        bound.print_only_trait_path(),
-                    ));
-                }
-            }
-            if !where_bounds.is_empty() {
-                err.help(&format!(
-                    "consider introducing a new type parameter `T` and adding `where` constraints:\
-                     \n    where\n        T: {},\n{}",
-                    ty_param_name(),
-                    where_bounds.join(",\n"),
-                ));
-            }
-            err.emit();
-            if !where_bounds.is_empty() {
-                return Err(ErrorReported);
-            }
-        }
-        Ok(bound)
-    }
-
-    fn complain_about_assoc_type_not_found<I>(
-        &self,
-        all_candidates: impl Fn() -> I,
-        ty_param_name: &str,
-        assoc_name: Ident,
-        span: Span,
-    ) where
-        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
-    {
-        // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
-        // valid span, so we point at the whole path segment instead.
-        let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
-        let mut err = struct_span_err!(
-            self.tcx().sess,
-            span,
-            E0220,
-            "associated type `{}` not found for `{}`",
-            assoc_name,
-            ty_param_name
-        );
-
-        let all_candidate_names: Vec<_> = all_candidates()
-            .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
-            .flatten()
-            .filter_map(
-                |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
-            )
-            .collect();
-
-        if let (Some(suggested_name), true) = (
-            find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
-            assoc_name.span != DUMMY_SP,
-        ) {
-            err.span_suggestion(
-                assoc_name.span,
-                "there is an associated type with a similar name",
-                suggested_name.to_string(),
-                Applicability::MaybeIncorrect,
-            );
-        } else {
-            err.span_label(span, format!("associated type `{}` not found", assoc_name));
-        }
-
-        err.emit();
-    }
-
-    // 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
-    // the whole path.
-    // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
-    // parameter or `Self`.
-    pub fn associated_path_to_ty(
-        &self,
-        hir_ref_id: hir::HirId,
-        span: Span,
-        qself_ty: Ty<'tcx>,
-        qself_res: Res,
-        assoc_segment: &hir::PathSegment<'_>,
-        permit_variants: bool,
-    ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorReported> {
-        let tcx = self.tcx();
-        let assoc_ident = assoc_segment.ident;
-
-        debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
-
-        // Check if we have an enum variant.
-        let mut variant_resolution = None;
-        if let ty::Adt(adt_def, _) = qself_ty.kind {
-            if adt_def.is_enum() {
-                let variant_def = adt_def
-                    .variants
-                    .iter()
-                    .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did));
-                if let Some(variant_def) = variant_def {
-                    if permit_variants {
-                        tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
-                        self.prohibit_generics(slice::from_ref(assoc_segment));
-                        return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
-                    } else {
-                        variant_resolution = Some(variant_def.def_id);
-                    }
-                }
-            }
-        }
-
-        // Find the type of the associated item, and the trait where the associated
-        // item is declared.
-        let bound = match (&qself_ty.kind, qself_res) {
-            (_, Res::SelfTy(Some(_), Some(impl_def_id))) => {
-                // `Self` in an impl of a trait -- we have a concrete self type and a
-                // trait reference.
-                let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
-                    Some(trait_ref) => trait_ref,
-                    None => {
-                        // A cycle error occurred, most likely.
-                        return Err(ErrorReported);
-                    }
-                };
-
-                self.one_bound_for_assoc_type(
-                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
-                    || "Self".to_string(),
-                    assoc_ident,
-                    span,
-                    || None,
-                )?
-            }
-            (
-                &ty::Param(_),
-                Res::SelfTy(Some(param_did), None) | Res::Def(DefKind::TyParam, param_did),
-            ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
-            _ => {
-                if variant_resolution.is_some() {
-                    // Variant in type position
-                    let msg = format!("expected type, found variant `{}`", assoc_ident);
-                    tcx.sess.span_err(span, &msg);
-                } else if qself_ty.is_enum() {
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        assoc_ident.span,
-                        E0599,
-                        "no variant named `{}` found for enum `{}`",
-                        assoc_ident,
-                        qself_ty,
-                    );
-
-                    let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
-                    if let Some(suggested_name) = find_best_match_for_name(
-                        adt_def.variants.iter().map(|variant| &variant.ident.name),
-                        assoc_ident.name,
-                        None,
-                    ) {
-                        err.span_suggestion(
-                            assoc_ident.span,
-                            "there is a variant with a similar name",
-                            suggested_name.to_string(),
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        err.span_label(
-                            assoc_ident.span,
-                            format!("variant not found in `{}`", qself_ty),
-                        );
-                    }
-
-                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
-                        let sp = tcx.sess.source_map().guess_head_span(sp);
-                        err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
-                    }
-
-                    err.emit();
-                } else if !qself_ty.references_error() {
-                    // Don't print `TyErr` to the user.
-                    self.report_ambiguous_associated_type(
-                        span,
-                        &qself_ty.to_string(),
-                        "Trait",
-                        assoc_ident.name,
-                    );
-                }
-                return Err(ErrorReported);
-            }
-        };
-
-        let trait_did = bound.def_id();
-        let (assoc_ident, def_scope) =
-            tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
-
-        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
-        // of calling `filter_by_name_and_kind`.
-        let item = tcx
-            .associated_items(trait_did)
-            .in_definition_order()
-            .find(|i| {
-                i.kind.namespace() == Namespace::TypeNS
-                    && i.ident.normalize_to_macros_2_0() == assoc_ident
-            })
-            .expect("missing associated type");
-
-        let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
-        let ty = self.normalize_ty(span, ty);
-
-        let kind = DefKind::AssocTy;
-        if !item.vis.is_accessible_from(def_scope, tcx) {
-            let kind = kind.descr(item.def_id);
-            let msg = format!("{} `{}` is private", kind, assoc_ident);
-            tcx.sess
-                .struct_span_err(span, &msg)
-                .span_label(span, &format!("private {}", kind))
-                .emit();
-        }
-        tcx.check_stability(item.def_id, Some(hir_ref_id), span);
-
-        if let Some(variant_def_id) = variant_resolution {
-            tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
-                let mut err = lint.build("ambiguous associated item");
-                let mut could_refer_to = |kind: DefKind, def_id, also| {
-                    let note_msg = format!(
-                        "`{}` could{} refer to the {} defined here",
-                        assoc_ident,
-                        also,
-                        kind.descr(def_id)
-                    );
-                    err.span_note(tcx.def_span(def_id), &note_msg);
-                };
-
-                could_refer_to(DefKind::Variant, variant_def_id, "");
-                could_refer_to(kind, item.def_id, " also");
-
-                err.span_suggestion(
-                    span,
-                    "use fully-qualified syntax",
-                    format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
-                    Applicability::MachineApplicable,
-                );
-
-                err.emit();
-            });
-        }
-        Ok((ty, kind, item.def_id))
-    }
-
-    fn qpath_to_ty(
-        &self,
-        span: Span,
-        opt_self_ty: Option<Ty<'tcx>>,
-        item_def_id: DefId,
-        trait_segment: &hir::PathSegment<'_>,
-        item_segment: &hir::PathSegment<'_>,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        let trait_def_id = tcx.parent(item_def_id).unwrap();
-
-        debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
-
-        let self_ty = if let Some(ty) = opt_self_ty {
-            ty
-        } else {
-            let path_str = tcx.def_path_str(trait_def_id);
-
-            let def_id = self.item_def_id();
-
-            debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
-
-            let parent_def_id = def_id
-                .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
-                })
-                .map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
-
-            debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
-
-            // If the trait in segment is the same as the trait defining the item,
-            // use the `<Self as ..>` syntax in the error.
-            let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
-            let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
-
-            let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
-                "Self"
-            } else {
-                "Type"
-            };
-
-            self.report_ambiguous_associated_type(
-                span,
-                type_name,
-                &path_str,
-                item_segment.ident.name,
-            );
-            return tcx.ty_error();
-        };
-
-        debug!("qpath_to_ty: self_type={:?}", self_ty);
-
-        let trait_ref = self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment);
-
-        let item_substs = self.create_substs_for_associated_item(
-            tcx,
-            span,
-            item_def_id,
-            item_segment,
-            trait_ref.substs,
-        );
-
-        debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
-
-        self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
-    }
-
-    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
-        &self,
-        segments: T,
-    ) -> bool {
-        let mut has_err = false;
-        for segment in segments {
-            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
-            for arg in segment.generic_args().args {
-                let (span, kind) = match arg {
-                    hir::GenericArg::Lifetime(lt) => {
-                        if err_for_lt {
-                            continue;
-                        }
-                        err_for_lt = true;
-                        has_err = true;
-                        (lt.span, "lifetime")
-                    }
-                    hir::GenericArg::Type(ty) => {
-                        if err_for_ty {
-                            continue;
-                        }
-                        err_for_ty = true;
-                        has_err = true;
-                        (ty.span, "type")
-                    }
-                    hir::GenericArg::Const(ct) => {
-                        if err_for_ct {
-                            continue;
-                        }
-                        err_for_ct = true;
-                        has_err = true;
-                        (ct.span, "const")
-                    }
-                };
-                let mut err = struct_span_err!(
-                    self.tcx().sess,
-                    span,
-                    E0109,
-                    "{} arguments are not allowed for this type",
-                    kind,
-                );
-                err.span_label(span, format!("{} argument not allowed", kind));
-                err.emit();
-                if err_for_lt && err_for_ty && err_for_ct {
-                    break;
-                }
-            }
-
-            // Only emit the first error to avoid overloading the user with error messages.
-            if let [binding, ..] = segment.generic_args().bindings {
-                has_err = true;
-                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
-            }
-        }
-        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,
-        segments: &[hir::PathSegment<'_>],
-        self_ty: Option<Ty<'tcx>>,
-        kind: DefKind,
-        def_id: DefId,
-    ) -> Vec<PathSeg> {
-        // We need to extract the type parameters supplied by the user in
-        // the path `path`. Due to the current setup, this is a bit of a
-        // tricky-process; the problem is that resolve only tells us the
-        // end-point of the path resolution, and not the intermediate steps.
-        // Luckily, we can (at least for now) deduce the intermediate steps
-        // just from the end-point.
-        //
-        // There are basically five cases to consider:
-        //
-        // 1. Reference to a constructor of a struct:
-        //
-        //        struct Foo<T>(...)
-        //
-        //    In this case, the parameters are declared in the type space.
-        //
-        // 2. Reference to a constructor of an enum variant:
-        //
-        //        enum E<T> { Foo(...) }
-        //
-        //    In this case, the parameters are defined in the type space,
-        //    but may be specified either on the type or the variant.
-        //
-        // 3. Reference to a fn item or a free constant:
-        //
-        //        fn foo<T>() { }
-        //
-        //    In this case, the path will again always have the form
-        //    `a::b::foo::<T>` where only the final segment should have
-        //    type parameters. However, in this case, those parameters are
-        //    declared on a value, and hence are in the `FnSpace`.
-        //
-        // 4. Reference to a method or an associated constant:
-        //
-        //        impl<A> SomeStruct<A> {
-        //            fn foo<B>(...)
-        //        }
-        //
-        //    Here we can have a path like
-        //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
-        //    may appear in two places. The penultimate segment,
-        //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
-        //    final segment, `foo::<B>` contains parameters in fn space.
-        //
-        // The first step then is to categorize the segments appropriately.
-
-        let tcx = self.tcx();
-
-        assert!(!segments.is_empty());
-        let last = segments.len() - 1;
-
-        let mut path_segs = vec![];
-
-        match kind {
-            // Case 1. Reference to a struct constructor.
-            DefKind::Ctor(CtorOf::Struct, ..) => {
-                // Everything but the final segment should have no
-                // parameters at all.
-                let generics = tcx.generics_of(def_id);
-                // Variant and struct constructors use the
-                // generics of their parent type definition.
-                let generics_def_id = generics.parent.unwrap_or(def_id);
-                path_segs.push(PathSeg(generics_def_id, last));
-            }
-
-            // Case 2. Reference to a variant constructor.
-            DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
-                let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
-                let (generics_def_id, index) = if let Some(adt_def) = adt_def {
-                    debug_assert!(adt_def.is_enum());
-                    (adt_def.did, last)
-                } else if last >= 1 && segments[last - 1].args.is_some() {
-                    // Everything but the penultimate segment should have no
-                    // parameters at all.
-                    let mut def_id = def_id;
-
-                    // `DefKind::Ctor` -> `DefKind::Variant`
-                    if let DefKind::Ctor(..) = kind {
-                        def_id = tcx.parent(def_id).unwrap()
-                    }
-
-                    // `DefKind::Variant` -> `DefKind::Enum`
-                    let enum_def_id = tcx.parent(def_id).unwrap();
-                    (enum_def_id, last - 1)
-                } else {
-                    // FIXME: lint here recommending `Enum::<...>::Variant` form
-                    // instead of `Enum::Variant::<...>` form.
-
-                    // Everything but the final segment should have no
-                    // parameters at all.
-                    let generics = tcx.generics_of(def_id);
-                    // Variant and struct constructors use the
-                    // generics of their parent type definition.
-                    (generics.parent.unwrap_or(def_id), last)
-                };
-                path_segs.push(PathSeg(generics_def_id, index));
-            }
-
-            // Case 3. Reference to a top-level value.
-            DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static => {
-                path_segs.push(PathSeg(def_id, last));
-            }
-
-            // Case 4. Reference to a method or associated const.
-            DefKind::AssocFn | DefKind::AssocConst => {
-                if segments.len() >= 2 {
-                    let generics = tcx.generics_of(def_id);
-                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
-                }
-                path_segs.push(PathSeg(def_id, last));
-            }
-
-            kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
-        }
-
-        debug!("path_segs = {:?}", path_segs);
-
-        path_segs
-    }
-
-    // Check a type `Path` and convert it to a `Ty`.
-    pub fn res_to_ty(
-        &self,
-        opt_self_ty: Option<Ty<'tcx>>,
-        path: &hir::Path<'_>,
-        permit_variants: bool,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        debug!(
-            "res_to_ty(res={:?}, opt_self_ty={:?}, path_segments={:?})",
-            path.res, opt_self_ty, path.segments
-        );
-
-        let span = path.span;
-        match path.res {
-            Res::Def(DefKind::OpaqueTy, did) => {
-                // Check for desugared `impl Trait`.
-                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
-                let item_segment = path.segments.split_last().unwrap();
-                self.prohibit_generics(item_segment.1);
-                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
-                self.normalize_ty(span, tcx.mk_opaque(did, substs))
-            }
-            Res::Def(
-                DefKind::Enum
-                | DefKind::TyAlias
-                | DefKind::Struct
-                | DefKind::Union
-                | DefKind::ForeignTy,
-                did,
-            ) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments.split_last().unwrap().1);
-                self.ast_path_to_ty(span, did, path.segments.last().unwrap())
-            }
-            Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
-                // Convert "variant type" as if it were a real type.
-                // The resulting `Ty` is type of the variant's enum for now.
-                assert_eq!(opt_self_ty, None);
-
-                let path_segs =
-                    self.def_ids_for_value_path_segments(&path.segments, None, kind, def_id);
-                let generic_segs: FxHashSet<_> =
-                    path_segs.iter().map(|PathSeg(_, index)| index).collect();
-                self.prohibit_generics(path.segments.iter().enumerate().filter_map(
-                    |(index, seg)| {
-                        if !generic_segs.contains(&index) { Some(seg) } else { None }
-                    },
-                ));
-
-                let PathSeg(def_id, index) = path_segs.last().unwrap();
-                self.ast_path_to_ty(span, *def_id, &path.segments[*index])
-            }
-            Res::Def(DefKind::TyParam, def_id) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-                let item_id = tcx.hir().get_parent_node(hir_id);
-                let item_def_id = tcx.hir().local_def_id(item_id);
-                let generics = tcx.generics_of(item_def_id);
-                let index = generics.param_def_id_to_index[&def_id];
-                tcx.mk_ty_param(index, tcx.hir().name(hir_id))
-            }
-            Res::SelfTy(Some(_), None) => {
-                // `Self` in trait or type alias.
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                tcx.types.self_param
-            }
-            Res::SelfTy(_, Some(def_id)) => {
-                // `Self` in impl (we know the concrete type).
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                // Try to evaluate any array length constants.
-                self.normalize_ty(span, tcx.at(span).type_of(def_id))
-            }
-            Res::Def(DefKind::AssocTy, def_id) => {
-                debug_assert!(path.segments.len() >= 2);
-                self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
-                self.qpath_to_ty(
-                    span,
-                    opt_self_ty,
-                    def_id,
-                    &path.segments[path.segments.len() - 2],
-                    path.segments.last().unwrap(),
-                )
-            }
-            Res::PrimTy(prim_ty) => {
-                assert_eq!(opt_self_ty, None);
-                self.prohibit_generics(path.segments);
-                match prim_ty {
-                    hir::PrimTy::Bool => tcx.types.bool,
-                    hir::PrimTy::Char => tcx.types.char,
-                    hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
-                    hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
-                    hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
-                    hir::PrimTy::Str => tcx.types.str_,
-                }
-            }
-            Res::Err => {
-                self.set_tainted_by_errors();
-                self.tcx().ty_error()
-            }
-            _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
-        }
-    }
-
-    /// Parses the programmer's textual representation of a type into our
-    /// internal notion of a type.
-    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
-        self.ast_ty_to_ty_inner(ast_ty, false)
-    }
-
-    /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
-    /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
-    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
-        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
-
-        let tcx = self.tcx();
-
-        let result_ty = match ast_ty.kind {
-            hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(&ty)),
-            hir::TyKind::Ptr(ref mt) => {
-                tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(&mt.ty), mutbl: mt.mutbl })
-            }
-            hir::TyKind::Rptr(ref region, ref mt) => {
-                let r = self.ast_region_to_region(region, None);
-                debug!("ast_ty_to_ty: r={:?}", r);
-                let t = self.ast_ty_to_ty_inner(&mt.ty, true);
-                tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
-            }
-            hir::TyKind::Never => tcx.types.never,
-            hir::TyKind::Tup(ref fields) => {
-                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
-            }
-            hir::TyKind::BareFn(ref bf) => {
-                require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-                tcx.mk_fn_ptr(self.ty_of_fn(
-                    bf.unsafety,
-                    bf.abi,
-                    &bf.decl,
-                    &hir::Generics::empty(),
-                    None,
-                ))
-            }
-            hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
-                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
-            }
-            hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
-                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
-                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
-                self.res_to_ty(opt_self_ty, path, false)
-            }
-            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
-                let opaque_ty = tcx.hir().expect_item(item_id.id);
-                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
-
-                match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
-                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
-                    }
-                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
-                }
-            }
-            hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
-                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
-                let ty = self.ast_ty_to_ty(qself);
-
-                let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
-                    path.res
-                } else {
-                    Res::Err
-                };
-                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
-                    .map(|(ty, _, _)| ty)
-                    .unwrap_or_else(|_| tcx.ty_error())
-            }
-            hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
-                let def_id = tcx.require_lang_item(lang_item, Some(span));
-                let (substs, _, _) = self.create_substs_for_ast_path(
-                    span,
-                    def_id,
-                    &[],
-                    &GenericArgs::none(),
-                    true,
-                    None,
-                );
-                self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
-            }
-            hir::TyKind::Array(ref ty, ref length) => {
-                let length_def_id = tcx.hir().local_def_id(length.hir_id);
-                let length = ty::Const::from_anon_const(tcx, length_def_id);
-                let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
-                self.normalize_ty(ast_ty.span, array_ty)
-            }
-            hir::TyKind::Typeof(ref _e) => {
-                struct_span_err!(
-                    tcx.sess,
-                    ast_ty.span,
-                    E0516,
-                    "`typeof` is a reserved keyword but unimplemented"
-                )
-                .span_label(ast_ty.span, "reserved keyword")
-                .emit();
-
-                tcx.ty_error()
-            }
-            hir::TyKind::Infer => {
-                // Infer also appears as the type of arguments or return
-                // values in a ExprKind::Closure, or as
-                // the type of local variables. Both of these cases are
-                // handled specially and will not descend into this routine.
-                self.ty_infer(None, ast_ty.span)
-            }
-            hir::TyKind::Err => tcx.ty_error(),
-        };
-
-        debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
-
-        self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
-        result_ty
-    }
-
-    pub fn impl_trait_ty_to_ty(
-        &self,
-        def_id: DefId,
-        lifetimes: &[hir::GenericArg<'_>],
-        replace_parent_lifetimes: bool,
-    ) -> Ty<'tcx> {
-        debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
-        let tcx = self.tcx();
-
-        let generics = tcx.generics_of(def_id);
-
-        debug!("impl_trait_ty_to_ty: generics={:?}", generics);
-        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
-            if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
-                // Our own parameters are the resolved lifetimes.
-                match param.kind {
-                    GenericParamDefKind::Lifetime => {
-                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
-                            self.ast_region_to_region(lifetime, None).into()
-                        } else {
-                            bug!()
-                        }
-                    }
-                    _ => bug!(),
-                }
-            } else {
-                match param.kind {
-                    // For RPIT (return position impl trait), only lifetimes
-                    // mentioned in the impl Trait predicate are captured by
-                    // the opaque type, so the lifetime parameters from the
-                    // parent item need to be replaced with `'static`.
-                    //
-                    // For `impl Trait` in the types of statics, constants,
-                    // locals and type aliases. These capture all parent
-                    // lifetimes, so they can use their identity subst.
-                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
-                        tcx.lifetimes.re_static.into()
-                    }
-                    _ => tcx.mk_param_from_def(param),
-                }
-            }
-        });
-        debug!("impl_trait_ty_to_ty: substs={:?}", substs);
-
-        let ty = tcx.mk_opaque(def_id, substs);
-        debug!("impl_trait_ty_to_ty: {}", ty);
-        ty
-    }
-
-    pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
-        match ty.kind {
-            hir::TyKind::Infer if expected_ty.is_some() => {
-                self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
-                expected_ty.unwrap()
-            }
-            _ => self.ast_ty_to_ty(ty),
-        }
-    }
-
-    pub fn ty_of_fn(
-        &self,
-        unsafety: hir::Unsafety,
-        abi: abi::Abi,
-        decl: &hir::FnDecl<'_>,
-        generics: &hir::Generics<'_>,
-        ident_span: Option<Span>,
-    ) -> ty::PolyFnSig<'tcx> {
-        debug!("ty_of_fn");
-
-        let tcx = self.tcx();
-
-        // We proactively collect all the inferred type params to emit a single error per fn def.
-        let mut visitor = PlaceholderHirTyCollector::default();
-        for ty in decl.inputs {
-            visitor.visit_ty(ty);
-        }
-        walk_generics(&mut visitor, generics);
-
-        let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
-        let output_ty = match decl.output {
-            hir::FnRetTy::Return(ref output) => {
-                visitor.visit_ty(output);
-                self.ast_ty_to_ty(output)
-            }
-            hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
-        };
-
-        debug!("ty_of_fn: output_ty={:?}", output_ty);
-
-        let bare_fn_ty =
-            ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
-
-        if !self.allow_ty_infer() {
-            // We always collect the spans for placeholder types when evaluating `fn`s, but we
-            // only want to emit an error complaining about them if infer types (`_`) are not
-            // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
-            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
-            crate::collect::placeholder_type_error(
-                tcx,
-                ident_span.map(|sp| sp.shrink_to_hi()),
-                &generics.params[..],
-                visitor.0,
-                true,
-            );
-        }
-
-        // Find any late-bound regions declared in return type that do
-        // not appear in the arguments. These are not well-formed.
-        //
-        // Example:
-        //     for<'a> fn() -> &'a str <-- 'a is bad
-        //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
-        let inputs = bare_fn_ty.inputs();
-        let late_bound_in_args =
-            tcx.collect_constrained_late_bound_regions(&inputs.map_bound(|i| i.to_owned()));
-        let output = bare_fn_ty.output();
-        let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
-
-        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
-            struct_span_err!(
-                tcx.sess,
-                decl.output.span(),
-                E0581,
-                "return type references {}, which is not constrained by the fn input types",
-                br_name
-            )
-        });
-
-        bare_fn_ty
-    }
-
-    fn validate_late_bound_regions(
-        &self,
-        constrained_regions: FxHashSet<ty::BoundRegion>,
-        referenced_regions: FxHashSet<ty::BoundRegion>,
-        generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
-    ) {
-        for br in referenced_regions.difference(&constrained_regions) {
-            let br_name = match *br {
-                ty::BrNamed(_, name) => format!("lifetime `{}`", name),
-                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
-            };
-
-            let mut err = generate_err(&br_name);
-
-            if let ty::BrAnon(_) = *br {
-                // The only way for an anonymous lifetime to wind up
-                // in the return type but **also** be unconstrained is
-                // if it only appears in "associated types" in the
-                // input. See #47511 and #62200 for examples. In this case,
-                // though we can easily give a hint that ought to be
-                // relevant.
-                err.note(
-                    "lifetimes appearing in an associated type are not considered constrained",
-                );
-            }
-
-            err.emit();
-        }
-    }
-
-    /// Given the bounds on an object, determines what single region bound (if any) we can
-    /// use to summarize this type. The basic idea is that we will use the bound the user
-    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
-    /// for region bounds. It may be that we can derive no bound at all, in which case
-    /// we return `None`.
-    fn compute_object_lifetime_bound(
-        &self,
-        span: Span,
-        existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-    ) -> Option<ty::Region<'tcx>> // if None, use the default
-    {
-        let tcx = self.tcx();
-
-        debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
-
-        // No explicit region bound specified. Therefore, examine trait
-        // bounds and see if we can derive region bounds from those.
-        let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
-
-        // If there are no derived region bounds, then report back that we
-        // can find no region bound. The caller will use the default.
-        if derived_region_bounds.is_empty() {
-            return None;
-        }
-
-        // If any of the derived region bounds are 'static, that is always
-        // the best choice.
-        if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
-            return Some(tcx.lifetimes.re_static);
-        }
-
-        // Determine whether there is exactly one unique region in the set
-        // of derived region bounds. If so, use that. Otherwise, report an
-        // error.
-        let r = derived_region_bounds[0];
-        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            struct_span_err!(
-                tcx.sess,
-                span,
-                E0227,
-                "ambiguous lifetime bound, explicit lifetime bound required"
-            )
-            .emit();
-        }
-        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<T: Bar + Baz>() { }
-///           ^^^^^^^^^ bounding the type parameter `T`
-///
-/// impl dyn Bar + Baz
-///          ^^^^^^^^^ bounding the forgotten dynamic type
-/// ```
-///
-/// Our representation is a bit mixed here -- in some cases, we
-/// include the self type (e.g., `trait_bounds`) but in others we do
-#[derive(Default, PartialEq, Eq, Clone, Debug)]
-pub struct Bounds<'tcx> {
-    /// A list of region bounds on the (implicit) self type. So if you
-    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
-    /// the `T` is not explicitly included).
-    pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
-
-    /// A list of trait bounds. So if you had `T: Debug` this would be
-    /// `T: Debug`. Note that the self-type is explicit here.
-    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
-
-    /// A list of projection equality bounds. So if you had `T:
-    /// Iterator<Item = u32>` this would include `<T as
-    /// Iterator>::Item => u32`. Note that the self-type is explicit
-    /// here.
-    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
-
-    /// `Some` if there is *no* `?Sized` predicate. The `span`
-    /// is the location in the source of the `T` declaration which can
-    /// be cited as the source of the `T: Sized` requirement.
-    pub implicitly_sized: Option<Span>,
-}
-
-impl<'tcx> Bounds<'tcx> {
-    /// Converts a bounds list into a flat set of predicates (like
-    /// where-clauses). Because some of our bounds listings (e.g.,
-    /// regions) don't include the self-type, you must supply the
-    /// self-type here (the `param_ty` parameter).
-    pub fn predicates(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        param_ty: Ty<'tcx>,
-    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-        // If it could be sized, and is, add the `Sized` predicate.
-        let sized_predicate = self.implicitly_sized.and_then(|span| {
-            tcx.lang_items().sized_trait().map(|sized| {
-                let trait_ref = ty::Binder::bind(ty::TraitRef {
-                    def_id: sized,
-                    substs: tcx.mk_substs_trait(param_ty, &[]),
-                });
-                (trait_ref.without_const().to_predicate(tcx), span)
-            })
-        });
-
-        sized_predicate
-            .into_iter()
-            .chain(
-                self.region_bounds
-                    .iter()
-                    .map(|&(region_bound, span)| {
-                        // Account for the binder being introduced below; no need to shift `param_ty`
-                        // because, at present at least, it either only refers to early-bound regions,
-                        // or it's a generic associated type that deliberately has escaping bound vars.
-                        let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
-                        let outlives = ty::OutlivesPredicate(param_ty, region_bound);
-                        (ty::Binder::bind(outlives).to_predicate(tcx), span)
-                    })
-                    .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
-                        let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
-                        (predicate, span)
-                    }))
-                    .chain(
-                        self.projection_bounds
-                            .iter()
-                            .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
-                    ),
-            )
-            .collect()
-    }
-}
diff --git a/src/librustc_typeck/astconv/errors.rs b/src/librustc_typeck/astconv/errors.rs
new file mode 100644 (file)
index 0000000..685243f
--- /dev/null
@@ -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<String>,
+        def_id: DefId,
+        span: Span,
+        empty_generic_args: bool,
+    ) {
+        if missing_type_params.is_empty() {
+            return;
+        }
+        let display =
+            missing_type_params.iter().map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            span,
+            E0393,
+            "the type parameter{} {} must be explicitly specified",
+            pluralize!(missing_type_params.len()),
+            display,
+        );
+        err.span_label(
+            self.tcx().def_span(def_id),
+            &format!(
+                "type parameter{} {} must be specified for this",
+                pluralize!(missing_type_params.len()),
+                display,
+            ),
+        );
+        let mut suggested = false;
+        if let (Ok(snippet), true) = (
+            self.tcx().sess.source_map().span_to_snippet(span),
+            // Don't suggest setting the type params if there are some already: the order is
+            // tricky to get right and the user will already know what the syntax is.
+            empty_generic_args,
+        ) {
+            if snippet.ends_with('>') {
+                // The user wrote `Trait<'a, T>` or similar. To provide an accurate suggestion
+                // we would have to preserve the right order. For now, as clearly the user is
+                // aware of the syntax, we do nothing.
+            } else {
+                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                // least we can clue them to the correct syntax `Iterator<Type>`.
+                err.span_suggestion(
+                    span,
+                    &format!(
+                        "set the type parameter{plural} to the desired type{plural}",
+                        plural = pluralize!(missing_type_params.len()),
+                    ),
+                    format!("{}<{}>", snippet, missing_type_params.join(", ")),
+                    Applicability::HasPlaceholders,
+                );
+                suggested = true;
+            }
+        }
+        if !suggested {
+            err.span_label(
+                span,
+                format!(
+                    "missing reference{} to {}",
+                    pluralize!(missing_type_params.len()),
+                    display,
+                ),
+            );
+        }
+        err.note(
+            "because of the default `Self` reference, type parameters must be \
+                  specified on object types",
+        );
+        err.emit();
+    }
+
+    /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
+    /// an error and attempt to build a reasonable structured suggestion.
+    pub(crate) fn complain_about_internal_fn_trait(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        trait_segment: &'a hir::PathSegment<'a>,
+    ) {
+        let trait_def = self.tcx().trait_def(trait_def_id);
+
+        if !self.tcx().features().unboxed_closures
+            && trait_segment.generic_args().parenthesized != trait_def.paren_sugar
+        {
+            let sess = &self.tcx().sess.parse_sess;
+            // For now, require that parenthetical notation be used only with `Fn()` etc.
+            let (msg, sugg) = if trait_def.paren_sugar {
+                (
+                    "the precise format of `Fn`-family traits' type parameters is subject to \
+                     change",
+                    Some(format!(
+                        "{}{} -> {}",
+                        trait_segment.ident,
+                        trait_segment
+                            .args
+                            .as_ref()
+                            .and_then(|args| args.args.get(0))
+                            .and_then(|arg| match arg {
+                                hir::GenericArg::Type(ty) => match ty.kind {
+                                    hir::TyKind::Tup(t) => t
+                                        .iter()
+                                        .map(|e| sess.source_map().span_to_snippet(e.span))
+                                        .collect::<Result<Vec<_>, _>>()
+                                        .map(|a| a.join(", ")),
+                                    _ => sess.source_map().span_to_snippet(ty.span),
+                                }
+                                .map(|s| format!("({})", s))
+                                .ok(),
+                                _ => None,
+                            })
+                            .unwrap_or_else(|| "()".to_string()),
+                        trait_segment
+                            .generic_args()
+                            .bindings
+                            .iter()
+                            .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
+                                (true, hir::TypeBindingKind::Equality { ty }) => {
+                                    sess.source_map().span_to_snippet(ty.span).ok()
+                                }
+                                _ => None,
+                            })
+                            .unwrap_or_else(|| "()".to_string()),
+                    )),
+                )
+            } else {
+                ("parenthetical notation is only stable when used with `Fn`-family traits", None)
+            };
+            let mut err = feature_err(sess, sym::unboxed_closures, span, msg);
+            if let Some(sugg) = sugg {
+                let msg = "use parenthetical notation instead";
+                err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect);
+            }
+            err.emit();
+        }
+    }
+
+    pub(crate) fn complain_about_assoc_type_not_found<I>(
+        &self,
+        all_candidates: impl Fn() -> I,
+        ty_param_name: &str,
+        assoc_name: Ident,
+        span: Span,
+    ) where
+        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
+    {
+        // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
+        // valid span, so we point at the whole path segment instead.
+        let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            span,
+            E0220,
+            "associated type `{}` not found for `{}`",
+            assoc_name,
+            ty_param_name
+        );
+
+        let all_candidate_names: Vec<_> = all_candidates()
+            .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
+            .flatten()
+            .filter_map(
+                |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
+            )
+            .collect();
+
+        if let (Some(suggested_name), true) = (
+            find_best_match_for_name(all_candidate_names.iter(), assoc_name.name, None),
+            assoc_name.span != DUMMY_SP,
+        ) {
+            err.span_suggestion(
+                assoc_name.span,
+                "there is an associated type with a similar name",
+                suggested_name.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            err.span_label(span, format!("associated type `{}` not found", assoc_name));
+        }
+
+        err.emit();
+    }
+
+    /// When there are any missing associated types, emit an E0191 error and attempt to supply a
+    /// reasonable suggestion on how to write it. For the case of multiple associated types in the
+    /// same trait bound have the same name (as they come from different super-traits), we instead
+    /// emit a generic note suggesting using a `where` clause to constraint instead.
+    pub(crate) fn complain_about_missing_associated_types(
+        &self,
+        associated_types: FxHashMap<Span, BTreeSet<DefId>>,
+        potential_assoc_types: Vec<Span>,
+        trait_bounds: &[hir::PolyTraitRef<'_>],
+    ) {
+        if associated_types.values().all(|v| v.is_empty()) {
+            return;
+        }
+        let tcx = self.tcx();
+        // FIXME: Marked `mut` so that we can replace the spans further below with a more
+        // appropriate one, but this should be handled earlier in the span assignment.
+        let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types
+            .into_iter()
+            .map(|(span, def_ids)| {
+                (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
+            })
+            .collect();
+        let mut names = vec![];
+
+        // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
+        // `issue-22560.rs`.
+        let mut trait_bound_spans: Vec<Span> = vec![];
+        for (span, items) in &associated_types {
+            if !items.is_empty() {
+                trait_bound_spans.push(*span);
+            }
+            for assoc_item in items {
+                let trait_def_id = assoc_item.container.id();
+                names.push(format!(
+                    "`{}` (from trait `{}`)",
+                    assoc_item.ident,
+                    tcx.def_path_str(trait_def_id),
+                ));
+            }
+        }
+        if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
+            match &bound.trait_ref.path.segments[..] {
+                // FIXME: `trait_ref.path.span` can point to a full path with multiple
+                // segments, even though `trait_ref.path.segments` is of length `1`. Work
+                // around that bug here, even though it should be fixed elsewhere.
+                // This would otherwise cause an invalid suggestion. For an example, look at
+                // `src/test/ui/issues/issue-28344.rs` where instead of the following:
+                //
+                //   error[E0191]: the value of the associated type `Output`
+                //                 (from trait `std::ops::BitXor`) must be specified
+                //   --> $DIR/issue-28344.rs:4:17
+                //    |
+                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+                //    |                 ^^^^^^ help: specify the associated type:
+                //    |                              `BitXor<Output = Type>`
+                //
+                // we would output:
+                //
+                //   error[E0191]: the value of the associated type `Output`
+                //                 (from trait `std::ops::BitXor`) must be specified
+                //   --> $DIR/issue-28344.rs:4:17
+                //    |
+                // LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
+                //    |                 ^^^^^^^^^^^^^ help: specify the associated type:
+                //    |                                     `BitXor::bitor<Output = Type>`
+                [segment] if segment.args.is_none() => {
+                    trait_bound_spans = vec![segment.ident.span];
+                    associated_types = associated_types
+                        .into_iter()
+                        .map(|(_, items)| (segment.ident.span, items))
+                        .collect();
+                }
+                _ => {}
+            }
+        }
+        names.sort();
+        trait_bound_spans.sort();
+        let mut err = struct_span_err!(
+            tcx.sess,
+            trait_bound_spans,
+            E0191,
+            "the value of the associated type{} {} must be specified",
+            pluralize!(names.len()),
+            names.join(", "),
+        );
+        let mut suggestions = vec![];
+        let mut types_count = 0;
+        let mut where_constraints = vec![];
+        for (span, assoc_items) in &associated_types {
+            let mut names: FxHashMap<_, usize> = FxHashMap::default();
+            for item in assoc_items {
+                types_count += 1;
+                *names.entry(item.ident.name).or_insert(0) += 1;
+            }
+            let mut dupes = false;
+            for item in assoc_items {
+                let prefix = if names[&item.ident.name] > 1 {
+                    let trait_def_id = item.container.id();
+                    dupes = true;
+                    format!("{}::", tcx.def_path_str(trait_def_id))
+                } else {
+                    String::new()
+                };
+                if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
+                    err.span_label(sp, format!("`{}{}` defined here", prefix, item.ident));
+                }
+            }
+            if potential_assoc_types.len() == assoc_items.len() {
+                // Only suggest when the amount of missing associated types equals the number of
+                // extra type arguments present, as that gives us a relatively high confidence
+                // that the user forgot to give the associtated type's name. The canonical
+                // example would be trying to use `Iterator<isize>` instead of
+                // `Iterator<Item = isize>`.
+                for (potential, item) in potential_assoc_types.iter().zip(assoc_items.iter()) {
+                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
+                        suggestions.push((*potential, format!("{} = {}", item.ident, snippet)));
+                    }
+                }
+            } else if let (Ok(snippet), false) =
+                (tcx.sess.source_map().span_to_snippet(*span), dupes)
+            {
+                let types: Vec<_> =
+                    assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect();
+                let code = if snippet.ends_with('>') {
+                    // The user wrote `Trait<'a>` or similar and we don't have a type we can
+                    // suggest, but at least we can clue them to the correct syntax
+                    // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
+                    // suggestion.
+                    format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
+                } else {
+                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                    // least we can clue them to the correct syntax `Iterator<Item = Type>`.
+                    format!("{}<{}>", snippet, types.join(", "))
+                };
+                suggestions.push((*span, code));
+            } else if dupes {
+                where_constraints.push(*span);
+            }
+        }
+        let where_msg = "consider introducing a new type parameter, adding `where` constraints \
+                         using the fully-qualified path to the associated types";
+        if !where_constraints.is_empty() && suggestions.is_empty() {
+            // If there are duplicates associated type names and a single trait bound do not
+            // use structured suggestion, it means that there are multiple super-traits with
+            // the same associated type name.
+            err.help(where_msg);
+        }
+        if suggestions.len() != 1 {
+            // We don't need this label if there's an inline suggestion, show otherwise.
+            for (span, assoc_items) in &associated_types {
+                let mut names: FxHashMap<_, usize> = FxHashMap::default();
+                for item in assoc_items {
+                    types_count += 1;
+                    *names.entry(item.ident.name).or_insert(0) += 1;
+                }
+                let mut label = vec![];
+                for item in assoc_items {
+                    let postfix = if names[&item.ident.name] > 1 {
+                        let trait_def_id = item.container.id();
+                        format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
+                    } else {
+                        String::new()
+                    };
+                    label.push(format!("`{}`{}", item.ident, postfix));
+                }
+                if !label.is_empty() {
+                    err.span_label(
+                        *span,
+                        format!(
+                            "associated type{} {} must be specified",
+                            pluralize!(label.len()),
+                            label.join(", "),
+                        ),
+                    );
+                }
+            }
+        }
+        if !suggestions.is_empty() {
+            err.multipart_suggestion(
+                &format!("specify the associated type{}", pluralize!(types_count)),
+                suggestions,
+                Applicability::HasPlaceholders,
+            );
+            if !where_constraints.is_empty() {
+                err.span_help(where_constraints, where_msg);
+            }
+        }
+        err.emit();
+    }
+}
diff --git a/src/librustc_typeck/astconv/generics.rs b/src/librustc_typeck/astconv/generics.rs
new file mode 100644 (file)
index 0000000..84dab6d
--- /dev/null
@@ -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 `<T as Foo>::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<Ty<'tcx>>,
+        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(&param) = 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(&param) = 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(&param)) => {
+                        match (arg, &param.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::<Vec<(ParamKindOrd, GenericParamDef)>>();
+                                    param_types_present.sort_by_key(|(ord, _)| *ord);
+                                    let (mut param_types_present, ordered_params): (
+                                        Vec<ParamKindOrd>,
+                                        Vec<GenericParamDef>,
+                                    ) = 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::<Vec<String>>()
+                                                .join(", then "),
+                                            ordered_params
+                                                .into_iter()
+                                                .filter_map(|param| {
+                                                    if param.name == kw::SelfUpper {
+                                                        None
+                                                    } else {
+                                                        Some(param.name.to_string())
+                                                    }
+                                                })
+                                                .collect::<Vec<String>>()
+                                                .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(&param)) => {
+                        // 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<Span>,
+                                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<Span> = 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::<Vec<_>>();
+
+            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/mod.rs b/src/librustc_typeck/astconv/mod.rs
new file mode 100644 (file)
index 0000000..15c19af
--- /dev/null
@@ -0,0 +1,2296 @@
+//! 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`.
+
+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;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+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};
+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::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;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
+use rustc_trait_selection::traits::wf::object_region_bounds;
+
+use smallvec::SmallVec;
+use std::collections::BTreeSet;
+use std::iter;
+use std::slice;
+
+#[derive(Debug)]
+pub struct PathSeg(pub DefId, pub usize);
+
+pub trait AstConv<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
+
+    fn item_def_id(&self) -> Option<DefId>;
+
+    fn default_constness_for_trait_bounds(&self) -> Constness;
+
+    /// Returns predicates in scope of the form `X: Foo`, where `X` is
+    /// a type parameter `X` with the given id `def_id`. This is a
+    /// subset of the full set of predicates.
+    ///
+    /// This is used for one specific purpose: resolving "short-hand"
+    /// associated type references like `T::Item`. In principle, we
+    /// would do that by first getting the full set of predicates in
+    /// scope and then filtering down to find those that apply to `T`,
+    /// but this can lead to cycle errors. The problem is that we have
+    /// to do this resolution *in order to create the predicates in
+    /// the first place*. Hence, we have this "special pass".
+    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
+
+    /// Returns the lifetime to use when a lifetime is omitted (and not elided).
+    fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
+    -> Option<ty::Region<'tcx>>;
+
+    /// Returns the type to use when a type is omitted.
+    fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
+
+    /// Returns `true` if `_` is allowed in type signatures in the current context.
+    fn allow_ty_infer(&self) -> bool;
+
+    /// Returns the const to use when a const is omitted.
+    fn ct_infer(
+        &self,
+        ty: Ty<'tcx>,
+        param: Option<&ty::GenericParamDef>,
+        span: Span,
+    ) -> &'tcx Const<'tcx>;
+
+    /// Projecting an associated type from a (potentially)
+    /// higher-ranked trait reference is more complicated, because of
+    /// the possibility of late-bound regions appearing in the
+    /// associated type binding. This is not legal in function
+    /// signatures for that reason. In a function body, we can always
+    /// handle it because we can use inference variables to remove the
+    /// late-bound regions.
+    fn projected_ty_from_poly_trait_ref(
+        &self,
+        span: Span,
+        item_def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Ty<'tcx>;
+
+    /// Normalize an associated type coming from the user.
+    fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>;
+
+    /// Invoked when we encounter an error from some prior pass
+    /// (e.g., resolve) that is translated into a ty-error. This is
+    /// used to help suppress derived errors typeck might otherwise
+    /// report.
+    fn set_tainted_by_errors(&self);
+
+    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
+}
+
+pub enum SizedByDefault {
+    Yes,
+    No,
+}
+
+struct ConvertedBinding<'a, 'tcx> {
+    item_name: Ident,
+    kind: ConvertedBindingKind<'a, 'tcx>,
+    span: Span,
+}
+
+enum ConvertedBindingKind<'a, 'tcx> {
+    Equality(Ty<'tcx>),
+    Constraint(&'a [hir::GenericBound<'a>]),
+}
+
+/// New-typed boolean indicating whether explicit late-bound lifetimes
+/// are present in a set of generic arguments.
+///
+/// For example if we have some method `fn f<'a>(&'a self)` implemented
+/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
+/// is late-bound so should not be provided explicitly. Thus, if `f` is
+/// instantiated with some generic arguments providing `'a` explicitly,
+/// we taint those arguments with `ExplicitLateBound::Yes` so that we
+/// can provide an appropriate diagnostic later.
+#[derive(Copy, Clone, PartialEq)]
+pub enum ExplicitLateBound {
+    Yes,
+    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)]
+pub(crate) enum GenericArgPosition {
+    Type,
+    Value, // e.g., functions
+    MethodCall,
+}
+
+/// A marker denoting that the generic arguments that were
+/// provided did not match the respective generic parameters.
+#[derive(Clone, Default)]
+pub struct GenericArgCountMismatch {
+    /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
+    pub reported: Option<ErrorReported>,
+    /// A list of spans of arguments provided that were not valid.
+    pub invalid_args: Vec<Span>,
+}
+
+/// Decorates the result of a generic argument count mismatch
+/// check with whether explicit late bounds were provided.
+#[derive(Clone)]
+pub struct GenericArgCountResult {
+    pub explicit_late_bound: ExplicitLateBound,
+    pub correct: Result<(), GenericArgCountMismatch>,
+}
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    pub fn ast_region_to_region(
+        &self,
+        lifetime: &hir::Lifetime,
+        def: Option<&ty::GenericParamDef>,
+    ) -> ty::Region<'tcx> {
+        let tcx = self.tcx();
+        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
+
+        let r = match tcx.named_region(lifetime.hir_id) {
+            Some(rl::Region::Static) => tcx.lifetimes.re_static,
+
+            Some(rl::Region::LateBound(debruijn, id, _)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(id, name)))
+            }
+
+            Some(rl::Region::LateBoundAnon(debruijn, index)) => {
+                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
+            }
+
+            Some(rl::Region::EarlyBound(index, id, _)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name }))
+            }
+
+            Some(rl::Region::Free(scope, id)) => {
+                let name = lifetime_name(id.expect_local());
+                tcx.mk_region(ty::ReFree(ty::FreeRegion {
+                    scope,
+                    bound_region: ty::BrNamed(id, name),
+                }))
+
+                // (*) -- not late-bound, won't change
+            }
+
+            None => {
+                self.re_infer(def, lifetime.span).unwrap_or_else(|| {
+                    // This indicates an illegal lifetime
+                    // elision. `resolve_lifetime` should have
+                    // reported an error in this case -- but if
+                    // not, let's error out.
+                    tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
+
+                    // Supply some dummy value. We don't have an
+                    // `re_error`, annoyingly, so use `'static`.
+                    tcx.lifetimes.re_static
+                })
+            }
+        };
+
+        debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
+
+        r
+    }
+
+    /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
+    /// returns an appropriate set of substitutions for this particular reference to `I`.
+    pub fn ast_path_substs_for_ty(
+        &self,
+        span: Span,
+        def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> SubstsRef<'tcx> {
+        let (substs, assoc_bindings, _) = self.create_substs_for_ast_path(
+            span,
+            def_id,
+            &[],
+            item_segment.generic_args(),
+            item_segment.infer_args,
+            None,
+        );
+
+        if let Some(b) = assoc_bindings.first() {
+            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+        }
+
+        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.
+    /// Also returns back constraints on associated types.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// T: std::ops::Index<usize, Output = u32>
+    /// ^1 ^^^^^^^^^^^^^^2 ^^^^3  ^^^^^^^^^^^4
+    /// ```
+    ///
+    /// 1. The `self_ty` here would refer to the type `T`.
+    /// 2. The path in question is the path to the trait `std::ops::Index`,
+    ///    which will have been resolved to a `def_id`
+    /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
+    ///    parameters are returned in the `SubstsRef`, the associated type bindings like
+    ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
+    ///
+    /// Note that the type listing given here is *exactly* what the user provided.
+    ///
+    /// For (generic) associated types
+    ///
+    /// ```
+    /// <Vec<u8> as Iterable<u8>>::Iter::<'a>
+    /// ```
+    ///
+    /// We have the parent substs are the substs for the parent trait:
+    /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
+    /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
+    /// lists: `[Vec<u8>, u8, 'a]`.
+    fn create_substs_for_ast_path<'a>(
+        &self,
+        span: Span,
+        def_id: DefId,
+        parent_substs: &[subst::GenericArg<'tcx>],
+        generic_args: &'a hir::GenericArgs<'_>,
+        infer_args: bool,
+        self_ty: Option<Ty<'tcx>>,
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
+        // If the type is parameterized by this region, then replace this
+        // region with the current anon region binding (in other words,
+        // whatever & would get replaced with).
+        debug!(
+            "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
+                generic_args={:?})",
+            def_id, self_ty, generic_args
+        );
+
+        let tcx = self.tcx();
+        let generic_params = tcx.generics_of(def_id);
+
+        if generic_params.has_self {
+            if generic_params.parent.is_some() {
+                // The parent is a trait so it should have at least one subst
+                // for the `Self` type.
+                assert!(!parent_substs.is_empty())
+            } else {
+                // This item (presumably a trait) needs a self-type.
+                assert!(self_ty.is_some());
+            }
+        } else {
+            assert!(self_ty.is_none() && parent_substs.is_empty());
+        }
+
+        let arg_count = Self::check_generic_arg_count(
+            tcx,
+            span,
+            &generic_params,
+            &generic_args,
+            GenericArgPosition::Type,
+            self_ty.is_some(),
+            infer_args,
+        );
+
+        let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
+        let default_needs_object_self = |param: &ty::GenericParamDef| {
+            if let GenericParamDefKind::Type { has_default, .. } = param.kind {
+                if is_object && has_default {
+                    let default_ty = tcx.at(span).type_of(param.def_id);
+                    let self_param = tcx.types.self_param;
+                    if default_ty.walk().any(|arg| arg == self_param.into()) {
+                        // There is no suitable inference default for a type parameter
+                        // that references self, in an object type.
+                        return true;
+                    }
+                }
+            }
+
+            false
+        };
+
+        let mut missing_type_params = vec![];
+        let mut inferred_params = vec![];
+        let substs = Self::create_substs_for_generic_args(
+            tcx,
+            def_id,
+            parent_substs,
+            self_ty.is_some(),
+            self_ty,
+            arg_count.clone(),
+            // Provide the generic args, and whether types should be inferred.
+            |did| {
+                if did == def_id {
+                    (Some(generic_args), infer_args)
+                } else {
+                    // The last component of this tuple is unimportant.
+                    (None, false)
+                }
+            },
+            // Provide substitutions for parameters for which (valid) arguments have been provided.
+            |param, arg| match (&param.kind, arg) {
+                (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
+                    self.ast_region_to_region(&lt, Some(param)).into()
+                }
+                (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
+                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
+                        inferred_params.push(ty.span);
+                        tcx.ty_error().into()
+                    } else {
+                        self.ast_ty_to_ty(&ty).into()
+                    }
+                }
+                (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+                    ty::Const::from_opt_const_arg_anon_const(
+                        tcx,
+                        ty::WithOptConstParam {
+                            did: tcx.hir().local_def_id(ct.value.hir_id),
+                            const_param_did: Some(param.def_id),
+                        },
+                    )
+                    .into()
+                }
+                _ => unreachable!(),
+            },
+            // Provide substitutions for parameters for which arguments are inferred.
+            |substs, param, infer_args| {
+                match param.kind {
+                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+                    GenericParamDefKind::Type { has_default, .. } => {
+                        if !infer_args && has_default {
+                            // No type parameter provided, but a default exists.
+
+                            // If we are converting an object type, then the
+                            // `Self` parameter is unknown. However, some of the
+                            // other type parameters may reference `Self` in their
+                            // defaults. This will lead to an ICE if we are not
+                            // careful!
+                            if default_needs_object_self(param) {
+                                missing_type_params.push(param.name.to_string());
+                                tcx.ty_error().into()
+                            } else {
+                                // This is a default type parameter.
+                                self.normalize_ty(
+                                    span,
+                                    tcx.at(span).type_of(param.def_id).subst_spanned(
+                                        tcx,
+                                        substs.unwrap(),
+                                        Some(span),
+                                    ),
+                                )
+                                .into()
+                            }
+                        } else if infer_args {
+                            // No type parameters were provided, we can infer all.
+                            let param =
+                                if !default_needs_object_self(param) { Some(param) } else { None };
+                            self.ty_infer(param, span).into()
+                        } else {
+                            // We've already errored above about the mismatch.
+                            tcx.ty_error().into()
+                        }
+                    }
+                    GenericParamDefKind::Const => {
+                        let ty = tcx.at(span).type_of(param.def_id);
+                        // FIXME(const_generics:defaults)
+                        if infer_args {
+                            // No const parameters were provided, we can infer all.
+                            self.ct_infer(ty, Some(param), span).into()
+                        } else {
+                            // We've already errored above about the mismatch.
+                            tcx.const_error(ty).into()
+                        }
+                    }
+                }
+            },
+        );
+
+        self.complain_about_missing_type_params(
+            missing_type_params,
+            def_id,
+            span,
+            generic_args.args.is_empty(),
+        );
+
+        // Convert associated-type bindings or constraints into a separate vector.
+        // Example: Given this:
+        //
+        //     T: Iterator<Item = u32>
+        //
+        // The `T` is passed in as a self-type; the `Item = u32` is
+        // not a "type parameter" of the `Iterator` trait, but rather
+        // a restriction on `<T as Iterator>::Item`, so it is passed
+        // back separately.
+        let assoc_bindings = generic_args
+            .bindings
+            .iter()
+            .map(|binding| {
+                let kind = match binding.kind {
+                    hir::TypeBindingKind::Equality { ref ty } => {
+                        ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty))
+                    }
+                    hir::TypeBindingKind::Constraint { ref bounds } => {
+                        ConvertedBindingKind::Constraint(bounds)
+                    }
+                };
+                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
+            })
+            .collect();
+
+        debug!(
+            "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
+            generic_params, self_ty, substs
+        );
+
+        (substs, assoc_bindings, arg_count)
+    }
+
+    crate fn create_substs_for_associated_item(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        item_def_id: DefId,
+        item_segment: &hir::PathSegment<'_>,
+        parent_substs: SubstsRef<'tcx>,
+    ) -> SubstsRef<'tcx> {
+        if tcx.generics_of(item_def_id).params.is_empty() {
+            self.prohibit_generics(slice::from_ref(item_segment));
+
+            parent_substs
+        } else {
+            self.create_substs_for_ast_path(
+                span,
+                item_def_id,
+                parent_substs,
+                item_segment.generic_args(),
+                item_segment.infer_args,
+                None,
+            )
+            .0
+        }
+    }
+
+    /// 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.
+    ///
+    /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T = X>`
+    /// are disallowed. Otherwise, they are pushed onto the vector given.
+    pub fn instantiate_mono_trait_ref(
+        &self,
+        trait_ref: &hir::TraitRef<'_>,
+        self_ty: Ty<'tcx>,
+    ) -> ty::TraitRef<'tcx> {
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+
+        self.ast_path_to_mono_trait_ref(
+            trait_ref.path.span,
+            trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
+            self_ty,
+            trait_ref.path.segments.last().unwrap(),
+        )
+    }
+
+    /// The given trait-ref must actually be a trait.
+    pub(super) fn instantiate_poly_trait_ref_inner(
+        &self,
+        trait_ref: &hir::TraitRef<'_>,
+        span: Span,
+        constness: Constness,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+    ) -> GenericArgCountResult {
+        let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+
+        debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
+
+        self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+
+        let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
+            trait_ref.path.span,
+            trait_def_id,
+            self_ty,
+            trait_ref.path.segments.last().unwrap(),
+        );
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+
+        bounds.trait_bounds.push((poly_trait_ref, span, constness));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in &assoc_bindings {
+            // Specify type to assert that error was already reported in `Err` case.
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                trait_ref.hir_ref_id,
+                poly_trait_ref,
+                binding,
+                bounds,
+                speculative,
+                &mut dup_bindings,
+                binding.span,
+            );
+            // Okay to ignore `Err` because of `ErrorReported` (see above).
+        }
+
+        debug!(
+            "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
+            trait_ref, bounds, poly_trait_ref
+        );
+
+        arg_count
+    }
+
+    /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
+    /// a full trait reference. The resulting trait reference is returned. This may also generate
+    /// auxiliary bounds, which are added to `bounds`.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// poly_trait_ref = Iterator<Item = u32>
+    /// self_ty = Foo
+    /// ```
+    ///
+    /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`.
+    ///
+    /// **A note on binders:** against our usual convention, there is an implied bounder around
+    /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions.
+    /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
+    /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
+    /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
+    /// however.
+    pub fn instantiate_poly_trait_ref(
+        &self,
+        poly_trait_ref: &hir::PolyTraitRef<'_>,
+        constness: Constness,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+    ) -> GenericArgCountResult {
+        self.instantiate_poly_trait_ref_inner(
+            &poly_trait_ref.trait_ref,
+            poly_trait_ref.span,
+            constness,
+            self_ty,
+            bounds,
+            false,
+        )
+    }
+
+    pub fn instantiate_lang_item_trait_ref(
+        &self,
+        lang_item: hir::LangItem,
+        span: Span,
+        hir_id: hir::HirId,
+        args: &GenericArgs<'_>,
+        self_ty: Ty<'tcx>,
+        bounds: &mut Bounds<'tcx>,
+    ) {
+        let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+
+        let (substs, assoc_bindings, _) =
+            self.create_substs_for_ast_path(span, trait_def_id, &[], args, false, Some(self_ty));
+        let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
+        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in assoc_bindings {
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                hir_id,
+                poly_trait_ref,
+                &binding,
+                bounds,
+                false,
+                &mut dup_bindings,
+                span,
+            );
+        }
+    }
+
+    fn ast_path_to_mono_trait_ref(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        self_ty: Ty<'tcx>,
+        trait_segment: &hir::PathSegment<'_>,
+    ) -> ty::TraitRef<'tcx> {
+        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() {
+            Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
+        }
+        ty::TraitRef::new(trait_def_id, substs)
+    }
+
+    fn create_substs_for_ast_trait_ref<'a>(
+        &self,
+        span: Span,
+        trait_def_id: DefId,
+        self_ty: Ty<'tcx>,
+        trait_segment: &'a hir::PathSegment<'a>,
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
+        debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
+
+        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
+
+        self.create_substs_for_ast_path(
+            span,
+            trait_def_id,
+            &[],
+            trait_segment.generic_args(),
+            trait_segment.infer_args,
+            Some(self_ty),
+        )
+    }
+
+    fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+        self.tcx()
+            .associated_items(trait_def_id)
+            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
+            .is_some()
+    }
+
+    // Returns `true` if a bounds list includes `?Sized`.
+    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+        let tcx = self.tcx();
+
+        // Try to find an unbound in bounds.
+        let mut unbound = None;
+        for ab in ast_bounds {
+            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+                if unbound.is_none() {
+                    unbound = Some(&ptr.trait_ref);
+                } else {
+                    struct_span_err!(
+                        tcx.sess,
+                        span,
+                        E0203,
+                        "type parameter has more than one relaxed default \
+                        bound, only one is supported"
+                    )
+                    .emit();
+                }
+            }
+        }
+
+        let kind_id = tcx.lang_items().require(SizedTraitLangItem);
+        match unbound {
+            Some(tpb) => {
+                // FIXME(#8559) currently requires the unbound to be built-in.
+                if let Ok(kind_id) = kind_id {
+                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
+                        tcx.sess.span_warn(
+                            span,
+                            "default bound relaxed for a type parameter, but \
+                             this does nothing because the given bound is not \
+                             a default; only `?Sized` is supported",
+                        );
+                    }
+                }
+            }
+            _ if kind_id.is_ok() => {
+                return false;
+            }
+            // No lang item for `Sized`, so we can't add it as a bound.
+            None => {}
+        }
+
+        true
+    }
+
+    /// This helper takes a *converted* parameter type (`param_ty`)
+    /// and an *unconverted* list of bounds:
+    ///
+    /// ```text
+    /// fn foo<T: Debug>
+    ///        ^  ^^^^^ `ast_bounds` parameter, in HIR form
+    ///        |
+    ///        `param_ty`, in ty form
+    /// ```
+    ///
+    /// It adds these `ast_bounds` into the `bounds` structure.
+    ///
+    /// **A note on binders:** there is an implied binder around
+    /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
+    /// for more details.
+    fn add_bounds(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[hir::GenericBound<'_>],
+        bounds: &mut Bounds<'tcx>,
+    ) {
+        let mut trait_bounds = Vec::new();
+        let mut region_bounds = Vec::new();
+
+        let constness = self.default_constness_for_trait_bounds();
+        for ast_bound in ast_bounds {
+            match *ast_bound {
+                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
+                    trait_bounds.push((b, constness))
+                }
+                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
+                    trait_bounds.push((b, Constness::NotConst))
+                }
+                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
+                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
+                    .instantiate_lang_item_trait_ref(
+                        lang_item, span, hir_id, args, param_ty, bounds,
+                    ),
+                hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
+            }
+        }
+
+        for (bound, constness) in trait_bounds {
+            let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds);
+        }
+
+        bounds.region_bounds.extend(
+            region_bounds.into_iter().map(|r| (self.ast_region_to_region(r, None), r.span)),
+        );
+    }
+
+    /// Translates a list of bounds from the HIR into the `Bounds` data structure.
+    /// The self-type for the bounds is given by `param_ty`.
+    ///
+    /// Example:
+    ///
+    /// ```
+    /// fn foo<T: Bar + Baz>() { }
+    ///        ^  ^^^^^^^^^ ast_bounds
+    ///        param_ty
+    /// ```
+    ///
+    /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be
+    /// considered `Sized` unless there is an explicit `?Sized` bound.  This would be true in the
+    /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
+    ///
+    /// `span` should be the declaration size of the parameter.
+    pub fn compute_bounds(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[hir::GenericBound<'_>],
+        sized_by_default: SizedByDefault,
+        span: Span,
+    ) -> Bounds<'tcx> {
+        let mut bounds = Bounds::default();
+
+        self.add_bounds(param_ty, ast_bounds, &mut bounds);
+        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
+
+        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
+            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
+        } else {
+            None
+        };
+
+        bounds
+    }
+
+    /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
+    /// onto `bounds`.
+    ///
+    /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
+    /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
+    /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
+    fn add_predicates_for_ast_type_binding(
+        &self,
+        hir_ref_id: hir::HirId,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        binding: &ConvertedBinding<'_, 'tcx>,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+        dup_bindings: &mut FxHashMap<DefId, Span>,
+        path_span: Span,
+    ) -> Result<(), ErrorReported> {
+        let tcx = self.tcx();
+
+        if !speculative {
+            // Given something like `U: SomeTrait<T = X>`, we want to produce a
+            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
+            // subtle in the event that `T` is defined in a supertrait of
+            // `SomeTrait`, because in that case we need to upcast.
+            //
+            // That is, consider this case:
+            //
+            // ```
+            // trait SubTrait: SuperTrait<i32> { }
+            // trait SuperTrait<A> { type T; }
+            //
+            // ... B: SubTrait<T = foo> ...
+            // ```
+            //
+            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
+
+            // Find any late-bound regions declared in `ty` that are not
+            // declared in the trait-ref. These are not well-formed.
+            //
+            // Example:
+            //
+            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
+            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
+            if let ConvertedBindingKind::Equality(ty) = binding.kind {
+                let late_bound_in_trait_ref =
+                    tcx.collect_constrained_late_bound_regions(&trait_ref);
+                let late_bound_in_ty =
+                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
+                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
+                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+
+                // FIXME: point at the type params that don't have appropriate lifetimes:
+                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                //                         ----  ----     ^^^^^^^
+                self.validate_late_bound_regions(
+                    late_bound_in_trait_ref,
+                    late_bound_in_ty,
+                    |br_name| {
+                        struct_span_err!(
+                            tcx.sess,
+                            binding.span,
+                            E0582,
+                            "binding for associated type `{}` references {}, \
+                             which does not appear in the trait input types",
+                            binding.item_name,
+                            br_name
+                        )
+                    },
+                );
+            }
+        }
+
+        let candidate =
+            if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
+                // Simple case: X is defined in the current trait.
+                trait_ref
+            } else {
+                // Otherwise, we have to walk through the supertraits to find
+                // those that do.
+                self.one_bound_for_assoc_type(
+                    || traits::supertraits(tcx, trait_ref),
+                    || trait_ref.print_only_trait_path().to_string(),
+                    binding.item_name,
+                    path_span,
+                    || match binding.kind {
+                        ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
+                        _ => None,
+                    },
+                )?
+            };
+
+        let (assoc_ident, def_scope) =
+            tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
+
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
+        // of calling `filter_by_name_and_kind`.
+        let assoc_ty = tcx
+            .associated_items(candidate.def_id())
+            .filter_by_name_unhygienic(assoc_ident.name)
+            .find(|i| {
+                i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
+            .expect("missing associated type");
+
+        if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
+            tcx.sess
+                .struct_span_err(
+                    binding.span,
+                    &format!("associated type `{}` is private", binding.item_name),
+                )
+                .span_label(binding.span, "private associated type")
+                .emit();
+        }
+        tcx.check_stability(assoc_ty.def_id, Some(hir_ref_id), binding.span);
+
+        if !speculative {
+            dup_bindings
+                .entry(assoc_ty.def_id)
+                .and_modify(|prev_span| {
+                    struct_span_err!(
+                        self.tcx().sess,
+                        binding.span,
+                        E0719,
+                        "the value of the associated type `{}` (from trait `{}`) \
+                         is already specified",
+                        binding.item_name,
+                        tcx.def_path_str(assoc_ty.container.id())
+                    )
+                    .span_label(binding.span, "re-bound here")
+                    .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
+                    .emit();
+                })
+                .or_insert(binding.span);
+        }
+
+        match binding.kind {
+            ConvertedBindingKind::Equality(ref ty) => {
+                // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
+                // the "projection predicate" for:
+                //
+                // `<T as Iterator>::Item = u32`
+                bounds.projection_bounds.push((
+                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
+                        projection_ty: ty::ProjectionTy::from_ref_and_name(
+                            tcx,
+                            trait_ref,
+                            binding.item_name,
+                        ),
+                        ty,
+                    }),
+                    binding.span,
+                ));
+            }
+            ConvertedBindingKind::Constraint(ast_bounds) => {
+                // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
+                //
+                // `<T as Iterator>::Item: Debug`
+                //
+                // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
+                // parameter to have a skipped binder.
+                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
+                self.add_bounds(param_ty, ast_bounds, bounds);
+            }
+        }
+        Ok(())
+    }
+
+    fn ast_path_to_ty(
+        &self,
+        span: Span,
+        did: DefId,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> Ty<'tcx> {
+        let substs = self.ast_path_substs_for_ty(span, did, item_segment);
+        self.normalize_ty(span, self.tcx().at(span).type_of(did).subst(self.tcx(), substs))
+    }
+
+    fn conv_object_ty_poly_trait_ref(
+        &self,
+        span: Span,
+        trait_bounds: &[hir::PolyTraitRef<'_>],
+        lifetime: &hir::Lifetime,
+        borrowed: bool,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        let mut bounds = Bounds::default();
+        let mut potential_assoc_types = Vec::new();
+        let dummy_self = self.tcx().types.trait_object_dummy_self;
+        for trait_bound in trait_bounds.iter().rev() {
+            if let GenericArgCountResult {
+                correct:
+                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
+                ..
+            } = self.instantiate_poly_trait_ref(
+                trait_bound,
+                Constness::NotConst,
+                dummy_self,
+                &mut bounds,
+            ) {
+                potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
+            }
+        }
+
+        // Expand trait aliases recursively and check that only one regular (non-auto) trait
+        // is used and no 'maybe' bounds are used.
+        let expanded_traits =
+            traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
+            expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
+        if regular_traits.len() > 1 {
+            let first_trait = &regular_traits[0];
+            let additional_trait = &regular_traits[1];
+            let mut err = struct_span_err!(
+                tcx.sess,
+                additional_trait.bottom().1,
+                E0225,
+                "only auto traits can be used as additional traits in a trait object"
+            );
+            additional_trait.label_with_exp_info(
+                &mut err,
+                "additional non-auto trait",
+                "additional use",
+            );
+            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
+            err.help(&format!(
+                "consider creating a new trait with all of these as super-traits and using that \
+                 trait here instead: `trait NewTrait: {} {{}}`",
+                regular_traits
+                    .iter()
+                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
+                    .collect::<Vec<_>>()
+                    .join(" + "),
+            ));
+            err.note(
+                "auto-traits like `Send` and `Sync` are traits that have special properties; \
+                 for more information on them, visit \
+                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+            );
+            err.emit();
+        }
+
+        if regular_traits.is_empty() && auto_traits.is_empty() {
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0224,
+                "at least one trait is required for an object type"
+            )
+            .emit();
+            return tcx.ty_error();
+        }
+
+        // Check that there are no gross object safety violations;
+        // most importantly, that the supertraits don't contain `Self`,
+        // to avoid ICEs.
+        for item in &regular_traits {
+            let object_safety_violations =
+                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
+            if !object_safety_violations.is_empty() {
+                report_object_safety_error(
+                    tcx,
+                    span,
+                    item.trait_ref().def_id(),
+                    &object_safety_violations[..],
+                )
+                .emit();
+                return tcx.ty_error();
+            }
+        }
+
+        // Use a `BTreeSet` to keep output in a more consistent order.
+        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
+
+        let regular_traits_refs_spans = bounds
+            .trait_bounds
+            .into_iter()
+            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
+
+        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
+            assert_eq!(constness, Constness::NotConst);
+
+            for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
+                debug!(
+                    "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
+                    obligation.predicate
+                );
+
+                match obligation.predicate.skip_binders() {
+                    ty::PredicateAtom::Trait(pred, _) => {
+                        let pred = ty::Binder::bind(pred);
+                        associated_types.entry(span).or_default().extend(
+                            tcx.associated_items(pred.def_id())
+                                .in_definition_order()
+                                .filter(|item| item.kind == ty::AssocKind::Type)
+                                .map(|item| item.def_id),
+                        );
+                    }
+                    ty::PredicateAtom::Projection(pred) => {
+                        let pred = ty::Binder::bind(pred);
+                        // A `Self` within the original bound will be substituted with a
+                        // `trait_object_dummy_self`, so check for that.
+                        let references_self =
+                            pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
+
+                        // If the projection output contains `Self`, force the user to
+                        // elaborate it explicitly to avoid a lot of complexity.
+                        //
+                        // The "classicaly useful" case is the following:
+                        // ```
+                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
+                        //         type MyOutput;
+                        //     }
+                        // ```
+                        //
+                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
+                        // but actually supporting that would "expand" to an infinitely-long type
+                        // `fix $ Ï„ â†’ dyn MyTrait<MyOutput = X, Output = <Ï„ as MyTrait>::MyOutput`.
+                        //
+                        // Instead, we force the user to write
+                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
+                        // the discussion in #56288 for alternatives.
+                        if !references_self {
+                            // Include projections defined on supertraits.
+                            bounds.projection_bounds.push((pred, span));
+                        }
+                    }
+                    _ => (),
+                }
+            }
+        }
+
+        for (projection_bound, _) in &bounds.projection_bounds {
+            for def_ids in associated_types.values_mut() {
+                def_ids.remove(&projection_bound.projection_def_id());
+            }
+        }
+
+        self.complain_about_missing_associated_types(
+            associated_types,
+            potential_assoc_types,
+            trait_bounds,
+        );
+
+        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
+        // `dyn Trait + Send`.
+        auto_traits.sort_by_key(|i| i.trait_ref().def_id());
+        auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
+        debug!("regular_traits: {:?}", regular_traits);
+        debug!("auto_traits: {:?}", auto_traits);
+
+        // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
+        // removing the dummy `Self` type (`trait_object_dummy_self`).
+        let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
+            if trait_ref.self_ty() != dummy_self {
+                // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
+                // which picks up non-supertraits where clauses - but also, the object safety
+                // completely ignores trait aliases, which could be object safety hazards. We
+                // `delay_span_bug` here to avoid an ICE in stable even when the feature is
+                // disabled. (#66420)
+                tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    &format!(
+                        "trait_ref_to_existential called on {:?} with non-dummy Self",
+                        trait_ref,
+                    ),
+                );
+            }
+            ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
+        };
+
+        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
+        let existential_trait_refs =
+            regular_traits.iter().map(|i| i.trait_ref().map_bound(trait_ref_to_existential));
+        let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
+            bound.map_bound(|b| {
+                let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
+                ty::ExistentialProjection {
+                    ty: b.ty,
+                    item_def_id: b.projection_ty.item_def_id,
+                    substs: trait_ref.substs,
+                }
+            })
+        });
+
+        // Calling `skip_binder` is okay because the predicates are re-bound.
+        let regular_trait_predicates = existential_trait_refs
+            .map(|trait_ref| ty::ExistentialPredicate::Trait(trait_ref.skip_binder()));
+        let auto_trait_predicates = auto_traits
+            .into_iter()
+            .map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
+        let mut v = regular_trait_predicates
+            .chain(auto_trait_predicates)
+            .chain(
+                existential_projections
+                    .map(|x| ty::ExistentialPredicate::Projection(x.skip_binder())),
+            )
+            .collect::<SmallVec<[_; 8]>>();
+        v.sort_by(|a, b| a.stable_cmp(tcx, b));
+        v.dedup();
+        let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
+
+        // Use explicitly-specified region bound.
+        let region_bound = if !lifetime.is_elided() {
+            self.ast_region_to_region(lifetime, None)
+        } else {
+            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
+                if tcx.named_region(lifetime.hir_id).is_some() {
+                    self.ast_region_to_region(lifetime, None)
+                } else {
+                    self.re_infer(None, span).unwrap_or_else(|| {
+                        let mut err = struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0228,
+                            "the lifetime bound for this object type cannot be deduced \
+                             from context; please supply an explicit bound"
+                        );
+                        if borrowed {
+                            // We will have already emitted an error E0106 complaining about a
+                            // missing named lifetime in `&dyn Trait`, so we elide this one.
+                            err.delay_as_bug();
+                        } else {
+                            err.emit();
+                        }
+                        tcx.lifetimes.re_static
+                    })
+                }
+            })
+        };
+        debug!("region_bound: {:?}", region_bound);
+
+        let ty = tcx.mk_dynamic(existential_predicates, region_bound);
+        debug!("trait_object_type: {:?}", ty);
+        ty
+    }
+
+    fn report_ambiguous_associated_type(
+        &self,
+        span: Span,
+        type_str: &str,
+        trait_str: &str,
+        name: Symbol,
+    ) {
+        let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
+        if let (Some(_), Ok(snippet)) = (
+            self.tcx().sess.confused_type_with_std_module.borrow().get(&span),
+            self.tcx().sess.source_map().span_to_snippet(span),
+        ) {
+            err.span_suggestion(
+                span,
+                "you are looking for the module in `std`, not the primitive type",
+                format!("std::{}", snippet),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            err.span_suggestion(
+                span,
+                "use fully-qualified syntax",
+                format!("<{} as {}>::{}", type_str, trait_str, name),
+                Applicability::HasPlaceholders,
+            );
+        }
+        err.emit();
+    }
+
+    // Search for a bound on a type parameter which includes the associated item
+    // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
+    // This function will fail if there are no suitable bounds or there is
+    // any ambiguity.
+    fn find_bound_for_assoc_item(
+        &self,
+        ty_param_def_id: LocalDefId,
+        assoc_name: Ident,
+        span: Span,
+    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported> {
+        let tcx = self.tcx();
+
+        debug!(
+            "find_bound_for_assoc_item(ty_param_def_id={:?}, assoc_name={:?}, span={:?})",
+            ty_param_def_id, assoc_name, span,
+        );
+
+        let predicates =
+            &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
+
+        debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
+
+        let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
+        let param_name = tcx.hir().ty_param_name(param_hir_id);
+        self.one_bound_for_assoc_type(
+            || {
+                traits::transitive_bounds(
+                    tcx,
+                    predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
+                )
+            },
+            || param_name.to_string(),
+            assoc_name,
+            span,
+            || None,
+        )
+    }
+
+    // Checks that `bounds` contains exactly one element and reports appropriate
+    // errors otherwise.
+    fn one_bound_for_assoc_type<I>(
+        &self,
+        all_candidates: impl Fn() -> I,
+        ty_param_name: impl Fn() -> String,
+        assoc_name: Ident,
+        span: Span,
+        is_equality: impl Fn() -> Option<String>,
+    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+    where
+        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
+    {
+        let mut matching_candidates = all_candidates()
+            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
+
+        let bound = match matching_candidates.next() {
+            Some(bound) => bound,
+            None => {
+                self.complain_about_assoc_type_not_found(
+                    all_candidates,
+                    &ty_param_name(),
+                    assoc_name,
+                    span,
+                );
+                return Err(ErrorReported);
+            }
+        };
+
+        debug!("one_bound_for_assoc_type: bound = {:?}", bound);
+
+        if let Some(bound2) = matching_candidates.next() {
+            debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
+
+            let is_equality = is_equality();
+            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
+            let mut err = if is_equality.is_some() {
+                // More specific Error Index entry.
+                struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0222,
+                    "ambiguous associated type `{}` in bounds of `{}`",
+                    assoc_name,
+                    ty_param_name()
+                )
+            } else {
+                struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0221,
+                    "ambiguous associated type `{}` in bounds of `{}`",
+                    assoc_name,
+                    ty_param_name()
+                )
+            };
+            err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
+
+            let mut where_bounds = vec![];
+            for bound in bounds {
+                let bound_id = bound.def_id();
+                let bound_span = self
+                    .tcx()
+                    .associated_items(bound_id)
+                    .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
+                    .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
+
+                if let Some(bound_span) = bound_span {
+                    err.span_label(
+                        bound_span,
+                        format!(
+                            "ambiguous `{}` from `{}`",
+                            assoc_name,
+                            bound.print_only_trait_path(),
+                        ),
+                    );
+                    if let Some(constraint) = &is_equality {
+                        where_bounds.push(format!(
+                            "        T: {trait}::{assoc} = {constraint}",
+                            trait=bound.print_only_trait_path(),
+                            assoc=assoc_name,
+                            constraint=constraint,
+                        ));
+                    } else {
+                        err.span_suggestion(
+                            span,
+                            "use fully qualified syntax to disambiguate",
+                            format!(
+                                "<{} as {}>::{}",
+                                ty_param_name(),
+                                bound.print_only_trait_path(),
+                                assoc_name,
+                            ),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                } else {
+                    err.note(&format!(
+                        "associated type `{}` could derive from `{}`",
+                        ty_param_name(),
+                        bound.print_only_trait_path(),
+                    ));
+                }
+            }
+            if !where_bounds.is_empty() {
+                err.help(&format!(
+                    "consider introducing a new type parameter `T` and adding `where` constraints:\
+                     \n    where\n        T: {},\n{}",
+                    ty_param_name(),
+                    where_bounds.join(",\n"),
+                ));
+            }
+            err.emit();
+            if !where_bounds.is_empty() {
+                return Err(ErrorReported);
+            }
+        }
+        Ok(bound)
+    }
+
+    // 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
+    // the whole path.
+    // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
+    // parameter or `Self`.
+    pub fn associated_path_to_ty(
+        &self,
+        hir_ref_id: hir::HirId,
+        span: Span,
+        qself_ty: Ty<'tcx>,
+        qself_res: Res,
+        assoc_segment: &hir::PathSegment<'_>,
+        permit_variants: bool,
+    ) -> Result<(Ty<'tcx>, DefKind, DefId), ErrorReported> {
+        let tcx = self.tcx();
+        let assoc_ident = assoc_segment.ident;
+
+        debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
+
+        // Check if we have an enum variant.
+        let mut variant_resolution = None;
+        if let ty::Adt(adt_def, _) = qself_ty.kind {
+            if adt_def.is_enum() {
+                let variant_def = adt_def
+                    .variants
+                    .iter()
+                    .find(|vd| tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did));
+                if let Some(variant_def) = variant_def {
+                    if permit_variants {
+                        tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
+                        self.prohibit_generics(slice::from_ref(assoc_segment));
+                        return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
+                    } else {
+                        variant_resolution = Some(variant_def.def_id);
+                    }
+                }
+            }
+        }
+
+        // Find the type of the associated item, and the trait where the associated
+        // item is declared.
+        let bound = match (&qself_ty.kind, qself_res) {
+            (_, Res::SelfTy(Some(_), Some(impl_def_id))) => {
+                // `Self` in an impl of a trait -- we have a concrete self type and a
+                // trait reference.
+                let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
+                    Some(trait_ref) => trait_ref,
+                    None => {
+                        // A cycle error occurred, most likely.
+                        return Err(ErrorReported);
+                    }
+                };
+
+                self.one_bound_for_assoc_type(
+                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
+                    || "Self".to_string(),
+                    assoc_ident,
+                    span,
+                    || None,
+                )?
+            }
+            (
+                &ty::Param(_),
+                Res::SelfTy(Some(param_did), None) | Res::Def(DefKind::TyParam, param_did),
+            ) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
+            _ => {
+                if variant_resolution.is_some() {
+                    // Variant in type position
+                    let msg = format!("expected type, found variant `{}`", assoc_ident);
+                    tcx.sess.span_err(span, &msg);
+                } else if qself_ty.is_enum() {
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        assoc_ident.span,
+                        E0599,
+                        "no variant named `{}` found for enum `{}`",
+                        assoc_ident,
+                        qself_ty,
+                    );
+
+                    let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
+                    if let Some(suggested_name) = find_best_match_for_name(
+                        adt_def.variants.iter().map(|variant| &variant.ident.name),
+                        assoc_ident.name,
+                        None,
+                    ) {
+                        err.span_suggestion(
+                            assoc_ident.span,
+                            "there is a variant with a similar name",
+                            suggested_name.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_label(
+                            assoc_ident.span,
+                            format!("variant not found in `{}`", qself_ty),
+                        );
+                    }
+
+                    if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
+                        let sp = tcx.sess.source_map().guess_head_span(sp);
+                        err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
+                    }
+
+                    err.emit();
+                } else if !qself_ty.references_error() {
+                    // Don't print `TyErr` to the user.
+                    self.report_ambiguous_associated_type(
+                        span,
+                        &qself_ty.to_string(),
+                        "Trait",
+                        assoc_ident.name,
+                    );
+                }
+                return Err(ErrorReported);
+            }
+        };
+
+        let trait_did = bound.def_id();
+        let (assoc_ident, def_scope) =
+            tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
+
+        // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
+        // of calling `filter_by_name_and_kind`.
+        let item = tcx
+            .associated_items(trait_did)
+            .in_definition_order()
+            .find(|i| {
+                i.kind.namespace() == Namespace::TypeNS
+                    && i.ident.normalize_to_macros_2_0() == assoc_ident
+            })
+            .expect("missing associated type");
+
+        let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
+        let ty = self.normalize_ty(span, ty);
+
+        let kind = DefKind::AssocTy;
+        if !item.vis.is_accessible_from(def_scope, tcx) {
+            let kind = kind.descr(item.def_id);
+            let msg = format!("{} `{}` is private", kind, assoc_ident);
+            tcx.sess
+                .struct_span_err(span, &msg)
+                .span_label(span, &format!("private {}", kind))
+                .emit();
+        }
+        tcx.check_stability(item.def_id, Some(hir_ref_id), span);
+
+        if let Some(variant_def_id) = variant_resolution {
+            tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
+                let mut err = lint.build("ambiguous associated item");
+                let mut could_refer_to = |kind: DefKind, def_id, also| {
+                    let note_msg = format!(
+                        "`{}` could{} refer to the {} defined here",
+                        assoc_ident,
+                        also,
+                        kind.descr(def_id)
+                    );
+                    err.span_note(tcx.def_span(def_id), &note_msg);
+                };
+
+                could_refer_to(DefKind::Variant, variant_def_id, "");
+                could_refer_to(kind, item.def_id, " also");
+
+                err.span_suggestion(
+                    span,
+                    "use fully-qualified syntax",
+                    format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
+                    Applicability::MachineApplicable,
+                );
+
+                err.emit();
+            });
+        }
+        Ok((ty, kind, item.def_id))
+    }
+
+    fn qpath_to_ty(
+        &self,
+        span: Span,
+        opt_self_ty: Option<Ty<'tcx>>,
+        item_def_id: DefId,
+        trait_segment: &hir::PathSegment<'_>,
+        item_segment: &hir::PathSegment<'_>,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        let trait_def_id = tcx.parent(item_def_id).unwrap();
+
+        debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
+
+        let self_ty = if let Some(ty) = opt_self_ty {
+            ty
+        } else {
+            let path_str = tcx.def_path_str(trait_def_id);
+
+            let def_id = self.item_def_id();
+
+            debug!("qpath_to_ty: self.item_def_id()={:?}", def_id);
+
+            let parent_def_id = def_id
+                .and_then(|def_id| {
+                    def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
+                })
+                .map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
+
+            debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id);
+
+            // If the trait in segment is the same as the trait defining the item,
+            // use the `<Self as ..>` syntax in the error.
+            let is_part_of_self_trait_constraints = def_id == Some(trait_def_id);
+            let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
+
+            let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
+                "Self"
+            } else {
+                "Type"
+            };
+
+            self.report_ambiguous_associated_type(
+                span,
+                type_name,
+                &path_str,
+                item_segment.ident.name,
+            );
+            return tcx.ty_error();
+        };
+
+        debug!("qpath_to_ty: self_type={:?}", self_ty);
+
+        let trait_ref = self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment);
+
+        let item_substs = self.create_substs_for_associated_item(
+            tcx,
+            span,
+            item_def_id,
+            item_segment,
+            trait_ref.substs,
+        );
+
+        debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
+
+        self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
+    }
+
+    pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
+        &self,
+        segments: T,
+    ) -> bool {
+        let mut has_err = false;
+        for segment in segments {
+            let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
+            for arg in segment.generic_args().args {
+                let (span, kind) = match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if err_for_lt {
+                            continue;
+                        }
+                        err_for_lt = true;
+                        has_err = true;
+                        (lt.span, "lifetime")
+                    }
+                    hir::GenericArg::Type(ty) => {
+                        if err_for_ty {
+                            continue;
+                        }
+                        err_for_ty = true;
+                        has_err = true;
+                        (ty.span, "type")
+                    }
+                    hir::GenericArg::Const(ct) => {
+                        if err_for_ct {
+                            continue;
+                        }
+                        err_for_ct = true;
+                        has_err = true;
+                        (ct.span, "const")
+                    }
+                };
+                let mut err = struct_span_err!(
+                    self.tcx().sess,
+                    span,
+                    E0109,
+                    "{} arguments are not allowed for this type",
+                    kind,
+                );
+                err.span_label(span, format!("{} argument not allowed", kind));
+                err.emit();
+                if err_for_lt && err_for_ty && err_for_ct {
+                    break;
+                }
+            }
+
+            // Only emit the first error to avoid overloading the user with error messages.
+            if let [binding, ..] = segment.generic_args().bindings {
+                has_err = true;
+                Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+            }
+        }
+        has_err
+    }
+
+    // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
+    pub fn def_ids_for_value_path_segments(
+        &self,
+        segments: &[hir::PathSegment<'_>],
+        self_ty: Option<Ty<'tcx>>,
+        kind: DefKind,
+        def_id: DefId,
+    ) -> Vec<PathSeg> {
+        // We need to extract the type parameters supplied by the user in
+        // the path `path`. Due to the current setup, this is a bit of a
+        // tricky-process; the problem is that resolve only tells us the
+        // end-point of the path resolution, and not the intermediate steps.
+        // Luckily, we can (at least for now) deduce the intermediate steps
+        // just from the end-point.
+        //
+        // There are basically five cases to consider:
+        //
+        // 1. Reference to a constructor of a struct:
+        //
+        //        struct Foo<T>(...)
+        //
+        //    In this case, the parameters are declared in the type space.
+        //
+        // 2. Reference to a constructor of an enum variant:
+        //
+        //        enum E<T> { Foo(...) }
+        //
+        //    In this case, the parameters are defined in the type space,
+        //    but may be specified either on the type or the variant.
+        //
+        // 3. Reference to a fn item or a free constant:
+        //
+        //        fn foo<T>() { }
+        //
+        //    In this case, the path will again always have the form
+        //    `a::b::foo::<T>` where only the final segment should have
+        //    type parameters. However, in this case, those parameters are
+        //    declared on a value, and hence are in the `FnSpace`.
+        //
+        // 4. Reference to a method or an associated constant:
+        //
+        //        impl<A> SomeStruct<A> {
+        //            fn foo<B>(...)
+        //        }
+        //
+        //    Here we can have a path like
+        //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
+        //    may appear in two places. The penultimate segment,
+        //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
+        //    final segment, `foo::<B>` contains parameters in fn space.
+        //
+        // The first step then is to categorize the segments appropriately.
+
+        let tcx = self.tcx();
+
+        assert!(!segments.is_empty());
+        let last = segments.len() - 1;
+
+        let mut path_segs = vec![];
+
+        match kind {
+            // Case 1. Reference to a struct constructor.
+            DefKind::Ctor(CtorOf::Struct, ..) => {
+                // Everything but the final segment should have no
+                // parameters at all.
+                let generics = tcx.generics_of(def_id);
+                // Variant and struct constructors use the
+                // generics of their parent type definition.
+                let generics_def_id = generics.parent.unwrap_or(def_id);
+                path_segs.push(PathSeg(generics_def_id, last));
+            }
+
+            // Case 2. Reference to a variant constructor.
+            DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
+                let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
+                let (generics_def_id, index) = if let Some(adt_def) = adt_def {
+                    debug_assert!(adt_def.is_enum());
+                    (adt_def.did, last)
+                } else if last >= 1 && segments[last - 1].args.is_some() {
+                    // Everything but the penultimate segment should have no
+                    // parameters at all.
+                    let mut def_id = def_id;
+
+                    // `DefKind::Ctor` -> `DefKind::Variant`
+                    if let DefKind::Ctor(..) = kind {
+                        def_id = tcx.parent(def_id).unwrap()
+                    }
+
+                    // `DefKind::Variant` -> `DefKind::Enum`
+                    let enum_def_id = tcx.parent(def_id).unwrap();
+                    (enum_def_id, last - 1)
+                } else {
+                    // FIXME: lint here recommending `Enum::<...>::Variant` form
+                    // instead of `Enum::Variant::<...>` form.
+
+                    // Everything but the final segment should have no
+                    // parameters at all.
+                    let generics = tcx.generics_of(def_id);
+                    // Variant and struct constructors use the
+                    // generics of their parent type definition.
+                    (generics.parent.unwrap_or(def_id), last)
+                };
+                path_segs.push(PathSeg(generics_def_id, index));
+            }
+
+            // Case 3. Reference to a top-level value.
+            DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static => {
+                path_segs.push(PathSeg(def_id, last));
+            }
+
+            // Case 4. Reference to a method or associated const.
+            DefKind::AssocFn | DefKind::AssocConst => {
+                if segments.len() >= 2 {
+                    let generics = tcx.generics_of(def_id);
+                    path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
+                }
+                path_segs.push(PathSeg(def_id, last));
+            }
+
+            kind => bug!("unexpected definition kind {:?} for {:?}", kind, def_id),
+        }
+
+        debug!("path_segs = {:?}", path_segs);
+
+        path_segs
+    }
+
+    // Check a type `Path` and convert it to a `Ty`.
+    pub fn res_to_ty(
+        &self,
+        opt_self_ty: Option<Ty<'tcx>>,
+        path: &hir::Path<'_>,
+        permit_variants: bool,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        debug!(
+            "res_to_ty(res={:?}, opt_self_ty={:?}, path_segments={:?})",
+            path.res, opt_self_ty, path.segments
+        );
+
+        let span = path.span;
+        match path.res {
+            Res::Def(DefKind::OpaqueTy, did) => {
+                // Check for desugared `impl Trait`.
+                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
+                let item_segment = path.segments.split_last().unwrap();
+                self.prohibit_generics(item_segment.1);
+                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
+                self.normalize_ty(span, tcx.mk_opaque(did, substs))
+            }
+            Res::Def(
+                DefKind::Enum
+                | DefKind::TyAlias
+                | DefKind::Struct
+                | DefKind::Union
+                | DefKind::ForeignTy,
+                did,
+            ) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments.split_last().unwrap().1);
+                self.ast_path_to_ty(span, did, path.segments.last().unwrap())
+            }
+            Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
+                // Convert "variant type" as if it were a real type.
+                // The resulting `Ty` is type of the variant's enum for now.
+                assert_eq!(opt_self_ty, None);
+
+                let path_segs =
+                    self.def_ids_for_value_path_segments(&path.segments, None, kind, def_id);
+                let generic_segs: FxHashSet<_> =
+                    path_segs.iter().map(|PathSeg(_, index)| index).collect();
+                self.prohibit_generics(path.segments.iter().enumerate().filter_map(
+                    |(index, seg)| {
+                        if !generic_segs.contains(&index) { Some(seg) } else { None }
+                    },
+                ));
+
+                let PathSeg(def_id, index) = path_segs.last().unwrap();
+                self.ast_path_to_ty(span, *def_id, &path.segments[*index])
+            }
+            Res::Def(DefKind::TyParam, def_id) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+                let item_id = tcx.hir().get_parent_node(hir_id);
+                let item_def_id = tcx.hir().local_def_id(item_id);
+                let generics = tcx.generics_of(item_def_id);
+                let index = generics.param_def_id_to_index[&def_id];
+                tcx.mk_ty_param(index, tcx.hir().name(hir_id))
+            }
+            Res::SelfTy(Some(_), None) => {
+                // `Self` in trait or type alias.
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                tcx.types.self_param
+            }
+            Res::SelfTy(_, Some(def_id)) => {
+                // `Self` in impl (we know the concrete type).
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                // Try to evaluate any array length constants.
+                self.normalize_ty(span, tcx.at(span).type_of(def_id))
+            }
+            Res::Def(DefKind::AssocTy, def_id) => {
+                debug_assert!(path.segments.len() >= 2);
+                self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
+                self.qpath_to_ty(
+                    span,
+                    opt_self_ty,
+                    def_id,
+                    &path.segments[path.segments.len() - 2],
+                    path.segments.last().unwrap(),
+                )
+            }
+            Res::PrimTy(prim_ty) => {
+                assert_eq!(opt_self_ty, None);
+                self.prohibit_generics(path.segments);
+                match prim_ty {
+                    hir::PrimTy::Bool => tcx.types.bool,
+                    hir::PrimTy::Char => tcx.types.char,
+                    hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
+                    hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
+                    hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
+                    hir::PrimTy::Str => tcx.types.str_,
+                }
+            }
+            Res::Err => {
+                self.set_tainted_by_errors();
+                self.tcx().ty_error()
+            }
+            _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
+        }
+    }
+
+    /// Parses the programmer's textual representation of a type into our
+    /// internal notion of a type.
+    pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+        self.ast_ty_to_ty_inner(ast_ty, false)
+    }
+
+    /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
+    /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
+    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
+        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
+
+        let tcx = self.tcx();
+
+        let result_ty = match ast_ty.kind {
+            hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(&ty)),
+            hir::TyKind::Ptr(ref mt) => {
+                tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(&mt.ty), mutbl: mt.mutbl })
+            }
+            hir::TyKind::Rptr(ref region, ref mt) => {
+                let r = self.ast_region_to_region(region, None);
+                debug!("ast_ty_to_ty: r={:?}", r);
+                let t = self.ast_ty_to_ty_inner(&mt.ty, true);
+                tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
+            }
+            hir::TyKind::Never => tcx.types.never,
+            hir::TyKind::Tup(ref fields) => {
+                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
+            }
+            hir::TyKind::BareFn(ref bf) => {
+                require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
+                tcx.mk_fn_ptr(self.ty_of_fn(
+                    bf.unsafety,
+                    bf.abi,
+                    &bf.decl,
+                    &hir::Generics::empty(),
+                    None,
+                ))
+            }
+            hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
+                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
+            }
+            hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
+                debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
+                let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
+                self.res_to_ty(opt_self_ty, path, false)
+            }
+            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
+                let opaque_ty = tcx.hir().expect_item(item_id.id);
+                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+
+                match opaque_ty.kind {
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
+                    }
+                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+                }
+            }
+            hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
+                debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
+                let ty = self.ast_ty_to_ty(qself);
+
+                let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind {
+                    path.res
+                } else {
+                    Res::Err
+                };
+                self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
+                    .map(|(ty, _, _)| ty)
+                    .unwrap_or_else(|_| tcx.ty_error())
+            }
+            hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
+                let def_id = tcx.require_lang_item(lang_item, Some(span));
+                let (substs, _, _) = self.create_substs_for_ast_path(
+                    span,
+                    def_id,
+                    &[],
+                    &GenericArgs::none(),
+                    true,
+                    None,
+                );
+                self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
+            }
+            hir::TyKind::Array(ref ty, ref length) => {
+                let length_def_id = tcx.hir().local_def_id(length.hir_id);
+                let length = ty::Const::from_anon_const(tcx, length_def_id);
+                let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
+                self.normalize_ty(ast_ty.span, array_ty)
+            }
+            hir::TyKind::Typeof(ref _e) => {
+                struct_span_err!(
+                    tcx.sess,
+                    ast_ty.span,
+                    E0516,
+                    "`typeof` is a reserved keyword but unimplemented"
+                )
+                .span_label(ast_ty.span, "reserved keyword")
+                .emit();
+
+                tcx.ty_error()
+            }
+            hir::TyKind::Infer => {
+                // Infer also appears as the type of arguments or return
+                // values in a ExprKind::Closure, or as
+                // the type of local variables. Both of these cases are
+                // handled specially and will not descend into this routine.
+                self.ty_infer(None, ast_ty.span)
+            }
+            hir::TyKind::Err => tcx.ty_error(),
+        };
+
+        debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
+
+        self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
+        result_ty
+    }
+
+    pub fn impl_trait_ty_to_ty(
+        &self,
+        def_id: DefId,
+        lifetimes: &[hir::GenericArg<'_>],
+        replace_parent_lifetimes: bool,
+    ) -> Ty<'tcx> {
+        debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
+        let tcx = self.tcx();
+
+        let generics = tcx.generics_of(def_id);
+
+        debug!("impl_trait_ty_to_ty: generics={:?}", generics);
+        let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
+            if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
+                // Our own parameters are the resolved lifetimes.
+                match param.kind {
+                    GenericParamDefKind::Lifetime => {
+                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
+                            self.ast_region_to_region(lifetime, None).into()
+                        } else {
+                            bug!()
+                        }
+                    }
+                    _ => bug!(),
+                }
+            } else {
+                match param.kind {
+                    // For RPIT (return position impl trait), only lifetimes
+                    // mentioned in the impl Trait predicate are captured by
+                    // the opaque type, so the lifetime parameters from the
+                    // parent item need to be replaced with `'static`.
+                    //
+                    // For `impl Trait` in the types of statics, constants,
+                    // locals and type aliases. These capture all parent
+                    // lifetimes, so they can use their identity subst.
+                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
+                        tcx.lifetimes.re_static.into()
+                    }
+                    _ => tcx.mk_param_from_def(param),
+                }
+            }
+        });
+        debug!("impl_trait_ty_to_ty: substs={:?}", substs);
+
+        let ty = tcx.mk_opaque(def_id, substs);
+        debug!("impl_trait_ty_to_ty: {}", ty);
+        ty
+    }
+
+    pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
+        match ty.kind {
+            hir::TyKind::Infer if expected_ty.is_some() => {
+                self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
+                expected_ty.unwrap()
+            }
+            _ => self.ast_ty_to_ty(ty),
+        }
+    }
+
+    pub fn ty_of_fn(
+        &self,
+        unsafety: hir::Unsafety,
+        abi: abi::Abi,
+        decl: &hir::FnDecl<'_>,
+        generics: &hir::Generics<'_>,
+        ident_span: Option<Span>,
+    ) -> ty::PolyFnSig<'tcx> {
+        debug!("ty_of_fn");
+
+        let tcx = self.tcx();
+
+        // We proactively collect all the inferred type params to emit a single error per fn def.
+        let mut visitor = PlaceholderHirTyCollector::default();
+        for ty in decl.inputs {
+            visitor.visit_ty(ty);
+        }
+        walk_generics(&mut visitor, generics);
+
+        let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
+        let output_ty = match decl.output {
+            hir::FnRetTy::Return(ref output) => {
+                visitor.visit_ty(output);
+                self.ast_ty_to_ty(output)
+            }
+            hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
+        };
+
+        debug!("ty_of_fn: output_ty={:?}", output_ty);
+
+        let bare_fn_ty =
+            ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
+
+        if !self.allow_ty_infer() {
+            // We always collect the spans for placeholder types when evaluating `fn`s, but we
+            // only want to emit an error complaining about them if infer types (`_`) are not
+            // allowed. `allow_ty_infer` gates this behavior. We check for the presence of
+            // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
+            crate::collect::placeholder_type_error(
+                tcx,
+                ident_span.map(|sp| sp.shrink_to_hi()),
+                &generics.params[..],
+                visitor.0,
+                true,
+            );
+        }
+
+        // Find any late-bound regions declared in return type that do
+        // not appear in the arguments. These are not well-formed.
+        //
+        // Example:
+        //     for<'a> fn() -> &'a str <-- 'a is bad
+        //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
+        let inputs = bare_fn_ty.inputs();
+        let late_bound_in_args =
+            tcx.collect_constrained_late_bound_regions(&inputs.map_bound(|i| i.to_owned()));
+        let output = bare_fn_ty.output();
+        let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
+
+        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
+            struct_span_err!(
+                tcx.sess,
+                decl.output.span(),
+                E0581,
+                "return type references {}, which is not constrained by the fn input types",
+                br_name
+            )
+        });
+
+        bare_fn_ty
+    }
+
+    fn validate_late_bound_regions(
+        &self,
+        constrained_regions: FxHashSet<ty::BoundRegion>,
+        referenced_regions: FxHashSet<ty::BoundRegion>,
+        generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
+    ) {
+        for br in referenced_regions.difference(&constrained_regions) {
+            let br_name = match *br {
+                ty::BrNamed(_, name) => format!("lifetime `{}`", name),
+                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
+            };
+
+            let mut err = generate_err(&br_name);
+
+            if let ty::BrAnon(_) = *br {
+                // The only way for an anonymous lifetime to wind up
+                // in the return type but **also** be unconstrained is
+                // if it only appears in "associated types" in the
+                // input. See #47511 and #62200 for examples. In this case,
+                // though we can easily give a hint that ought to be
+                // relevant.
+                err.note(
+                    "lifetimes appearing in an associated type are not considered constrained",
+                );
+            }
+
+            err.emit();
+        }
+    }
+
+    /// Given the bounds on an object, determines what single region bound (if any) we can
+    /// use to summarize this type. The basic idea is that we will use the bound the user
+    /// provided, if they provided one, and otherwise search the supertypes of trait bounds
+    /// for region bounds. It may be that we can derive no bound at all, in which case
+    /// we return `None`.
+    fn compute_object_lifetime_bound(
+        &self,
+        span: Span,
+        existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
+    ) -> Option<ty::Region<'tcx>> // if None, use the default
+    {
+        let tcx = self.tcx();
+
+        debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates);
+
+        // No explicit region bound specified. Therefore, examine trait
+        // bounds and see if we can derive region bounds from those.
+        let derived_region_bounds = object_region_bounds(tcx, existential_predicates);
+
+        // If there are no derived region bounds, then report back that we
+        // can find no region bound. The caller will use the default.
+        if derived_region_bounds.is_empty() {
+            return None;
+        }
+
+        // If any of the derived region bounds are 'static, that is always
+        // the best choice.
+        if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
+            return Some(tcx.lifetimes.re_static);
+        }
+
+        // Determine whether there is exactly one unique region in the set
+        // of derived region bounds. If so, use that. Otherwise, report an
+        // error.
+        let r = derived_region_bounds[0];
+        if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
+            struct_span_err!(
+                tcx.sess,
+                span,
+                E0227,
+                "ambiguous lifetime bound, explicit lifetime bound required"
+            )
+            .emit();
+        }
+        Some(r)
+    }
+}
diff --git a/src/librustc_typeck/bounds.rs b/src/librustc_typeck/bounds.rs
new file mode 100644 (file)
index 0000000..63295f5
--- /dev/null
@@ -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<T: Bar + Baz>() { }
+///           ^^^^^^^^^ bounding the type parameter `T`
+///
+/// impl dyn Bar + Baz
+///          ^^^^^^^^^ bounding the forgotten dynamic type
+/// ```
+///
+/// Our representation is a bit mixed here -- in some cases, we
+/// include the self type (e.g., `trait_bounds`) but in others we do not
+#[derive(Default, PartialEq, Eq, Clone, Debug)]
+pub struct Bounds<'tcx> {
+    /// A list of region bounds on the (implicit) self type. So if you
+    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
+    /// the `T` is not explicitly included).
+    pub region_bounds: Vec<(ty::Region<'tcx>, Span)>,
+
+    /// A list of trait bounds. So if you had `T: Debug` this would be
+    /// `T: Debug`. Note that the self-type is explicit here.
+    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
+
+    /// A list of projection equality bounds. So if you had `T:
+    /// Iterator<Item = u32>` this would include `<T as
+    /// Iterator>::Item => u32`. Note that the self-type is explicit
+    /// here.
+    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
+
+    /// `Some` if there is *no* `?Sized` predicate. The `span`
+    /// is the location in the source of the `T` declaration which can
+    /// be cited as the source of the `T: Sized` requirement.
+    pub implicitly_sized: Option<Span>,
+}
+
+impl<'tcx> Bounds<'tcx> {
+    /// Converts a bounds list into a flat set of predicates (like
+    /// where-clauses). Because some of our bounds listings (e.g.,
+    /// regions) don't include the self-type, you must supply the
+    /// self-type here (the `param_ty` parameter).
+    pub fn predicates(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_ty: Ty<'tcx>,
+    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+        // If it could be sized, and is, add the `Sized` predicate.
+        let sized_predicate = self.implicitly_sized.and_then(|span| {
+            tcx.lang_items().sized_trait().map(|sized| {
+                let trait_ref = ty::Binder::bind(ty::TraitRef {
+                    def_id: sized,
+                    substs: tcx.mk_substs_trait(param_ty, &[]),
+                });
+                (trait_ref.without_const().to_predicate(tcx), span)
+            })
+        });
+
+        sized_predicate
+            .into_iter()
+            .chain(
+                self.region_bounds
+                    .iter()
+                    .map(|&(region_bound, span)| {
+                        // Account for the binder being introduced below; no need to shift `param_ty`
+                        // because, at present at least, it either only refers to early-bound regions,
+                        // or it's a generic associated type that deliberately has escaping bound vars.
+                        let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
+                        let outlives = ty::OutlivesPredicate(param_ty, region_bound);
+                        (ty::Binder::bind(outlives).to_predicate(tcx), span)
+                    })
+                    .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
+                        let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
+                        (predicate, span)
+                    }))
+                    .chain(
+                        self.projection_bounds
+                            .iter()
+                            .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
+                    ),
+            )
+            .collect()
+    }
+}
index 7fb4026117be9d71b7aadcbce1ec80bb7c29ab99..9afac60bb5bb78b669b15f989408d476212a9dc0 100644 (file)
@@ -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;
index 4248253172598c877d82b0554e95e9faa6d0d69c..62f92fe7ffa484859e2699610230ba8ae827740a 100644 (file)
@@ -79,6 +79,7 @@
 pub mod expr_use_visitor;
 
 mod astconv;
+mod bounds;
 mod check_unused;
 mod coherence;
 mod collect;
 
 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) {
index 0a836f46c0eb85bc96bc861e94f3af109e58eb1c..671e082556722e8e08ef94c0700cbc52135e6d24 100644 (file)
@@ -3,7 +3,7 @@
 use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::html::markdown::{find_testable_code, ErrorCodes};
-use crate::passes::doc_test_lints::Tests;
+use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
 use crate::passes::Pass;
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
@@ -27,20 +27,29 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C
     krate
 }
 
-#[derive(Default, Copy, Clone, Serialize)]
+#[derive(Default, Copy, Clone, Serialize, Debug)]
 struct ItemCount {
     total: u64,
     with_docs: u64,
+    total_examples: u64,
     with_examples: u64,
 }
 
 impl ItemCount {
-    fn count_item(&mut self, has_docs: bool, has_doc_example: bool) {
+    fn count_item(
+        &mut self,
+        has_docs: bool,
+        has_doc_example: bool,
+        should_have_doc_examples: bool,
+    ) {
         self.total += 1;
 
         if has_docs {
             self.with_docs += 1;
         }
+        if should_have_doc_examples || has_doc_example {
+            self.total_examples += 1;
+        }
         if has_doc_example {
             self.with_examples += 1;
         }
@@ -55,8 +64,8 @@ fn percentage(&self) -> Option<f64> {
     }
 
     fn examples_percentage(&self) -> Option<f64> {
-        if self.total > 0 {
-            Some((self.with_examples as f64 * 100.0) / self.total as f64)
+        if self.total_examples > 0 {
+            Some((self.with_examples as f64 * 100.0) / self.total_examples as f64)
         } else {
             None
         }
@@ -70,6 +79,7 @@ fn sub(self, rhs: Self) -> Self {
         ItemCount {
             total: self.total - rhs.total,
             with_docs: self.with_docs - rhs.with_docs,
+            total_examples: self.total_examples - rhs.total_examples,
             with_examples: self.with_examples - rhs.with_examples,
         }
     }
@@ -79,6 +89,7 @@ impl ops::AddAssign for ItemCount {
     fn add_assign(&mut self, rhs: Self) {
         self.total += rhs.total;
         self.with_docs += rhs.with_docs;
+        self.total_examples += rhs.total_examples;
         self.with_examples += rhs.with_examples;
     }
 }
@@ -121,7 +132,7 @@ fn print_results(&self, output_format: Option<OutputFormat>) {
         let mut total = ItemCount::default();
 
         fn print_table_line() {
-            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
+            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
         }
 
         fn print_table_record(
@@ -131,32 +142,25 @@ fn print_table_record(
             examples_percentage: f64,
         ) {
             println!(
-                "| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
-                name,
-                count.with_docs,
-                count.total,
-                percentage,
-                count.with_examples,
-                examples_percentage,
+                "| {:<35} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
+                name, count.with_docs, percentage, count.with_examples, examples_percentage,
             );
         }
 
         print_table_line();
         println!(
-            "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |",
-            "File", "Documented", "Total", "Percentage", "Examples", "Percentage",
+            "| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} |",
+            "File", "Documented", "Percentage", "Examples", "Percentage",
         );
         print_table_line();
 
         for (file, &count) in &self.items {
-            if let (Some(percentage), Some(examples_percentage)) =
-                (count.percentage(), count.examples_percentage())
-            {
+            if let Some(percentage) = count.percentage() {
                 print_table_record(
                     &limit_filename_len(file.to_string()),
                     count,
                     percentage,
-                    examples_percentage,
+                    count.examples_percentage().unwrap_or(0.),
                 );
 
                 total += count;
@@ -176,19 +180,6 @@ fn print_table_record(
 
 impl fold::DocFolder for CoverageCalculator {
     fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
-        let has_docs = !i.attrs.doc_strings.is_empty();
-        let mut tests = Tests { found_tests: 0 };
-
-        find_testable_code(
-            &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
-            &mut tests,
-            ErrorCodes::No,
-            false,
-            None,
-        );
-
-        let has_doc_example = tests.found_tests != 0;
-
         match i.inner {
             _ if !i.def_id.is_local() => {
                 // non-local items are skipped because they can be out of the users control,
@@ -237,11 +228,24 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
                 }
             }
             _ => {
+                let has_docs = !i.attrs.doc_strings.is_empty();
+                let mut tests = Tests { found_tests: 0 };
+
+                find_testable_code(
+                    &i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
+                    &mut tests,
+                    ErrorCodes::No,
+                    false,
+                    None,
+                );
+
+                let has_doc_example = tests.found_tests != 0;
                 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_example(&i.inner),
+                );
             }
         }
 
index 97b9fcce05b362e72d2ddd06926a5151256cea00..9c57435a8c01613c8927c67ce7847b6b18b9ed69 100644 (file)
@@ -636,7 +636,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                 }
 
                 match disambiguator.map(Disambiguator::ns) {
-                    Some(ns @ ValueNS) => {
+                    Some(ns @ (ValueNS | TypeNS)) => {
                         match self.resolve(
                             path_str,
                             disambiguator,
@@ -660,28 +660,6 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                             }
                         }
                     }
-                    Some(ns @ TypeNS) => {
-                        match self.resolve(
-                            path_str,
-                            disambiguator,
-                            ns,
-                            &current_item,
-                            base_node,
-                            &extra_fragment,
-                            Some(&item),
-                        ) {
-                            Ok(res) => res,
-                            Err(ErrorKind::ResolutionFailure) => {
-                                resolution_failure(cx, &item, path_str, &dox, link_range);
-                                // This could just be a normal link.
-                                continue;
-                            }
-                            Err(ErrorKind::AnchorFailure(msg)) => {
-                                anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
-                                continue;
-                            }
-                        }
-                    }
                     None => {
                         // Try everything!
                         let mut candidates = PerNS {
index 1fdc4ee247adfc6a34b39c0f14051d59b9fae37d..a465a5f681f5c16e5e1da949b604aa7757e0b846 100644 (file)
@@ -4,6 +4,7 @@
 //! - PRIVATE_DOC_TESTS: this looks for private items with doc-tests.
 
 use super::{span_of_attrs, Pass};
+use crate::clean;
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
@@ -59,6 +60,22 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
     }
 }
 
+pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
+    !matches!(item_kind,
+        clean::StructFieldItem(_)
+        | clean::VariantItem(_)
+        | clean::AssocConstItem(_, _)
+        | clean::AssocTypeItem(_, _)
+        | clean::TypedefItem(_, _)
+        | clean::StaticItem(_)
+        | clean::ConstantItem(_)
+        | clean::ExternCrateItem(_, _)
+        | clean::ImportItem(_)
+        | clean::PrimitiveItem(_)
+        | clean::KeywordItem(_)
+    )
+}
+
 pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
         Some(hir_id) => hir_id,
@@ -73,13 +90,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
     find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
 
     if tests.found_tests == 0 {
-        use ItemEnum::*;
-
-        let should_report = match item.inner {
-            ExternCrateItem(_, _) | ImportItem(_) | PrimitiveItem(_) | KeywordItem(_) => false,
-            _ => true,
-        };
-        if should_report {
+        if should_have_doc_example(&item.inner) {
             debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
             let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
             cx.tcx.struct_span_lint_hir(
index a8df350ef60b2b6d91a1dbfd5800ad7fe349dcfa..e39f74c916c4ad4a7a233a10c701b2ba1ec39621 100644 (file)
@@ -553,3 +553,8 @@ pub unsafe fn $func(x: $ty) -> $ty {
 // CHECK: fmov s0, s0
 // CHECK: //NO_APP
 check_reg!(v0_f64x2 f64x2 "s0" "fmov");
+
+// Regression test for #75761
+pub unsafe fn issue_75761() {
+    asm!("", out("v0") _, out("x30") _);
+}
index 7e795acc575bccd51debfbea00fdd055b534cf23..3c602b3da4c7c8952347566f6acb16fbcf7ebea4 100644 (file)
@@ -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 (file)
index 0000000..1da1813
--- /dev/null
@@ -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 (file)
index 0000000..92f5855
--- /dev/null
@@ -0,0 +1 @@
+{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}}
index f25cf79a3f35d45876f1989e0633376e6acb4773..10ed13c9ff566c76d169649cc58949d7031dd442 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index 2a6a2231e5b5727e009ce2751fcee1431298d250..890a7d56e162d09bb8e0cc933a75d261cc634a26 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index dd86f61f8d5014f31b286581d0cc76cc4f1c508b..64c012c1f66e3dfea1eea7a743511b78a08e0f5f 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index f920a3abd36bb6dbcee91e32d4a98856bac68480..e282ff128437513e3a88564d4c564db7ce263d8c 100644 (file)
@@ -1,8 +1,8 @@
-+-------------------------------------+------------+------------+------------+------------+------------+
-| File                                | Documented |      Total | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| ...st/rustdoc-ui/coverage/exotic.rs |          1 |          1 |     100.0% |          0 |       0.0% |
-| <anon>                              |          2 |          2 |     100.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
-| Total                               |          3 |          3 |     100.0% |          0 |       0.0% |
-+-------------------------------------+------------+------------+------------+------------+------------+
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...st/rustdoc-ui/coverage/exotic.rs |          1 |     100.0% |          0 |       0.0% |
+| <anon>                              |          2 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          3 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index 2bd6a312ab58366207acc87b14237d58f23ffcba..a591cd5dba406ec1a0a29f72b163d9e6dab3eaae 100644 (file)
@@ -12,16 +12,54 @@ pub enum Bar { A }
 pub struct X;
 
 /// Bar
+///
+/// ```
+/// let x = 12;
+/// ```
 pub mod bar {
     /// bar
     pub struct Bar;
     /// X
-    pub enum X { Y }
+    pub enum X {
+        /// ```
+        /// let x = "should be ignored!";
+        /// ```
+        Y
+    }
 }
 
 /// yolo
+///
+/// ```text
+/// should not be counted as a code example!
+/// ```
 pub enum Yolo { X }
 
+impl Yolo {
+    /// ```
+    /// let x = "should be ignored!";
+    /// ```
+    pub const Const: u32 = 0;
+}
+
 pub struct Xo<T: Clone> {
+    /// ```
+    /// let x = "should be ignored!";
+    /// ```
     x: T,
 }
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub static StaticFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub const ConstFoo: u32 = 0;
+
+/// ```
+/// let x = "should be ignored!";
+/// ```
+pub type TypeFoo = u32;
index 7b5b083e1584c01a1e6fde7688feec686921acb7..c2be73ce3edd7c14b99a46e3445948ed27187041 100644 (file)
@@ -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}}
index bca3d51da59d066bc3eff24336d57c2fc405fbe9..37a0f5187b5122fc745e20f6a195db081dd36a43 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index 31b48cc602a76246763bf371fa0ac6935abeaf5a..dbea3a3ea23cf5f98a59f1611d89ed805545b647 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index ac63b65023d0b302449627c4a4699ddf71374d6a..e04d48b4980c4c299859b70d16bee676c0745c4e 100644 (file)
@@ -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% |
++-------------------------------------+------------+------------+------------+------------+
index ffe0ddcd8c9b2fc800d724db7a371c10a95f36fb..ebe7a242211bf50aa9dbbba4e00709068516a0b7 100644 (file)
@@ -38,3 +38,34 @@ pub mod module3 {
   //~^ ERROR
   pub fn test() {}
 }
+
+/// Doc, but no code example and it's fine!
+pub const Const: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub static Static: u32 = 0;
+/// Doc, but no code example and it's fine!
+pub type Type = u32;
+
+/// Doc
+//~^ ERROR
+pub struct Struct {
+    /// Doc, but no code example and it's fine!
+    pub field: u32,
+}
+
+/// Doc
+//~^ ERROR
+pub enum Enum {
+    /// Doc, but no code example and it's fine!
+    X,
+}
+
+/// Doc
+//~^ ERROR
+#[repr(C)]
+union Union {
+    /// Doc, but no code example and it's fine!
+    a: i32,
+    /// Doc, but no code example and it's fine!
+    b: f32,
+}
index 3fcfc1808e079aa8f035a33a2da9aaea631770c0..32756c99e7f9fde9822c46b2829ebdb58a872eb9 100644 (file)
@@ -1,9 +1,8 @@
 error: missing code example in this documentation
-  --> $DIR/lint-missing-doc-code-example.rs:19:1
+  --> $DIR/lint-missing-doc-code-example.rs:49:1
    |
-LL | / mod module1 {
-LL | | }
-   | |_^
+LL | /// Doc
+   | ^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-missing-doc-code-example.rs:2:9
@@ -11,11 +10,30 @@ note: the lint level is defined here
 LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:63:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:56:1
+   |
+LL | /// Doc
+   | ^^^^^^^
+
+error: missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:19:1
+   |
+LL | / mod module1 {
+LL | | }
+   | |_^
+
 error: missing code example in this documentation
   --> $DIR/lint-missing-doc-code-example.rs:37:3
    |
 LL |   /// doc
    |   ^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 5 previous errors
 
index 6962ccdec73eea52e084c6a99f9be43598792e87..8a6f7de1c9fbd3562990e8b592b7828a1f14656d 100644 (file)
@@ -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)]
index 32233a0f6eeb71183ac1da766e3aa8d09faf0805..dc2661ee796856816b8865c3361dccf17717a507 100644 (file)
@@ -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);
    |                           -^^^^^^^