rust-lang/rust · #164964

Rollup of 5 pull requests

JonathanBrouwer · merged Oct 26, 202616 files · 317 + / 284 −
.github/workflows/ci.yml1 + / 1 −
@@ -195,7 +195,7 @@ jobs:         # discoverable Python in $env:PATH. Only install if we're actually running Windows tests         # that use LLDB         if: ${{ startsWith(matrix.os, 'windows') && matrix.required_python_version}}-        uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0+        uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0         with:           python-version: ${{ matrix.required_python_version }} 
compiler/rustc_ast/src/attr/mod.rs0 + / 22 −
@@ -11,7 +11,6 @@ use rustc_span::{Ident, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; -use crate::GeneratedAttr; use crate::ast::{     AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,     Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,@@ -248,21 +247,6 @@ impl AttributeExt for Attribute {         }     } -    fn is_automatically_derived_attr(&self) -> bool {-        self.has_name(sym::automatically_derived)-    }--    fn is_doc_hidden(&self) -> bool {-        match &self.kind {-            AttrKind::Normal(_) => {-                self.has_name(sym::doc)-                    && self.meta_item_list().is_some_and(|l| list_contains_name(&l, sym::hidden))-            }-            AttrKind::Generated(GeneratedAttr::DocHidden) => true,-            _ => false,-        }-    }-     fn is_doc_keyword_or_attribute(&self) -> bool {         match &self.kind {             AttrKind::Normal(_) => {@@ -1000,9 +984,6 @@ pub trait AttributeExt: Debug + 'static {     /// i.e. `proc_macro`, `proc_macro_attribute` or `proc_macro_derive`.     fn is_proc_macro_attr(&self) -> bool; -    /// Returns true if this attribute is `#[automatically_deived]`.-    fn is_automatically_derived_attr(&self) -> bool;-     /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.     /// * `///doc` returns `Some(("doc", CommentKind::Line))`.     /// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.@@ -1019,9 +1000,6 @@ pub trait AttributeExt: Debug + 'static {     /// doc).     fn doc_resolution_scope(&self) -> Option<AttrStyle>; -    /// Returns `true` if this attribute contains `doc(hidden)`.-    fn is_doc_hidden(&self) -> bool;-     /// Returns `true` is this attribute contains `doc(keyword)` or `doc(attribute)`.     fn is_doc_keyword_or_attribute(&self) -> bool; 
compiler/rustc_attr_ir/src/attr.rs0 + / 8 −
@@ -226,10 +226,6 @@ impl AttributeExt for Attribute {         }     } -    fn is_automatically_derived_attr(&self) -> bool {-        matches!(self, Attribute::Parsed(AttributeKind::AutomaticallyDerived))-    }-     #[inline]     fn doc_str_and_fragment_kind(&self) -> Option<(Symbol, DocFragmentKind, Span)> {         match &self {@@ -261,10 +257,6 @@ impl AttributeExt for Attribute {         )     } -    fn is_doc_hidden(&self) -> bool {-        matches!(self, Attribute::Parsed(AttributeKind::Doc(d)) if d.hidden.is_some())-    }-     fn is_doc_keyword_or_attribute(&self) -> bool {         matches!(self, Attribute::Parsed(AttributeKind::Doc(d)) if d.attribute.is_some() || d.keyword.is_some())     }
compiler/rustc_lint/src/levels.rs31 + / 56 −
@@ -2,10 +2,9 @@ use std::fmt::Debug;  use rustc_ast as ast; use rustc_ast::CRATE_NODE_ID;-use rustc_ast::attr::AttributeExt; use rustc_attr_ir::lint::{LintCheck, LintCheckKind}; use rustc_attr_ir::target::Target;-use rustc_attr_ir::{Attribute, AttributeKind, find_attr};+use rustc_attr_ir::{Attribute, DocAttribute, find_attr}; use rustc_attr_parsing::{AttributeParser, Recovery, ShouldEmit}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordSet;@@ -32,7 +31,6 @@ use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; use rustc_span::def_id::CRATE_MOD_ID; use rustc_span::{AttrId, DUMMY_SP, Ident, Span, Symbol, sym};-use thin_vec::ThinVec; use tracing::{debug, instrument};  use crate::builtin::MISSING_DOCS;@@ -293,7 +291,7 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> { impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {     fn add_id(&mut self, hir_id: HirId) {         self.provider.cur = hir_id;-        self.add(self.provider.attrs.get(hir_id.local_id), hir_id == hir::CRATE_HIR_ID);+        self.add_hir(self.provider.attrs.get(hir_id.local_id), hir_id == hir::CRATE_HIR_ID);     } } @@ -413,7 +411,7 @@ impl<'s> LintLevelsBuilder<'s, TopDown> {         crate_attrs: &[ast::Attribute],     ) -> Self {         let mut builder = Self::new(sess, features, lint_added_lints, store, registered_lint_tools);-        builder.add(crate_attrs, true);+        builder.add_ast(crate_attrs, true);         builder     } @@ -445,7 +443,7 @@ impl<'s> LintLevelsBuilder<'s, TopDown> {         self.provider.cur =             self.provider.sets.list.push(LintSet { specs: FxIndexMap::default(), parent: prev }); -        self.add(attrs, is_crate_node);+        self.add_ast(attrs, is_crate_node);          if self.provider.current_specs().is_empty() {             self.provider.sets.list.pop();@@ -655,31 +653,22 @@ where         };     } -    fn parse_lint_attributes(-        &mut self,-        attrs: &[impl AttributeExt + 'static],-    ) -> ThinVec<LintCheck> {-        fn try_cast_slice<T: 'static, U: 'static>(slice: &[T]) -> Option<&[U]> {-            use std::any::TypeId;-            if TypeId::of::<T>() == TypeId::of::<U>() {-                // SAFETY: T == U, so it is sound to cast `&[T]` to `&[U]`-                unsafe {-                    Some(core::slice::from_raw_parts(slice.as_ptr().cast::<U>(), slice.len()))-                }-            } else {-                None-            }+    fn add_ast(&mut self, attrs: &[rustc_ast::Attribute], is_crate_node: bool) {+        if attrs.is_empty() {+            return;         }--        if let Some(attrs) = try_cast_slice::<_, rustc_attr_ir::Attribute>(attrs) {-            return find_attr!(attrs, LintCheck(lints) => lints.clone()).unwrap_or_default();+        for attr in attrs {+            // `SINGLE_USE_LIFETIMES` is an AST lint so we only insert this here+            if attr.has_name(sym::automatically_derived) {+                self.provider.insert(+                    LintId::of(SINGLE_USE_LIFETIMES),+                    LevelSpec::new(Level::Allow, None, LintLevelSource::Default),+                );+            }         }-         let parsed = AttributeParser::parse_limited_all(             self.sess,-            try_cast_slice(attrs).unwrap_or_else(|| {-                unreachable!("unknown `&[implAttributeExt]` {}", std::any::type_name_of_val(attrs))-            }),+            attrs,             Some(&|attr| {                 // This is ...complicated. Sometimes we need to parse lint check                 // attributes pre-expansion, but of course things are allowed to@@ -713,41 +702,27 @@ where             ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },             Some(self.registered_lint_tools),         );-        parsed-            .into_iter()-            .find_map(|p| {-                if let Attribute::Parsed(AttributeKind::LintCheck(lints)) = p {-                    Some(lints)-                } else {-                    None-                }-            })-            .unwrap_or_default()+        self.add_hir_inner(&parsed, is_crate_node)     } -    fn add(&mut self, attrs: &[impl AttributeExt + 'static], is_crate_node: bool) {+    fn add_hir(&mut self, attrs: &[Attribute], is_crate_node: bool) {         if attrs.is_empty() {             return;         }-        for attr in attrs {-            if attr.is_automatically_derived_attr() {-                self.provider.insert(-                    LintId::of(SINGLE_USE_LIFETIMES),-                    LevelSpec::new(Level::Allow, None, LintLevelSource::Default),-                );-                continue;-            }--            // `#[doc(hidden)]` disables missing_docs check.-            if attr.is_doc_hidden() {-                self.provider.insert(-                    LintId::of(MISSING_DOCS),-                    LevelSpec::new(Level::Allow, None, LintLevelSource::Default),-                );-                continue;-            }+        // `MISSING_DOCS` is a HIR lint so we only insert this here+        if find_attr!(attrs, Doc(DocAttribute { hidden: Some(_), .. })) {+            self.provider.insert(+                LintId::of(MISSING_DOCS),+                LevelSpec::new(Level::Allow, None, LintLevelSource::Default),+            );         }-        let lint_checks = self.parse_lint_attributes(attrs);+        self.add_hir_inner(attrs, is_crate_node)+    }++    fn add_hir_inner(&mut self, attrs: &[Attribute], is_crate_node: bool) {+        let Some(lint_checks) = find_attr!(attrs, LintCheck(lints) => lints.clone()) else {+            return;+        };          let sess = self.sess; 
library/alloc/src/collections/linked_list.rs115 + / 41 −
@@ -168,8 +168,8 @@ impl<T, A: Allocator> LinkedList<T, A> {     /// Adds the given node to the front of the list.     ///     /// # Safety-    /// `node` must point to a valid node in the list's allocator.-    /// This method takes ownership of the node, so the pointer should not be used again.+    ///+    /// `node` must point to a valid owned node in the list's allocator.     #[inline]     unsafe fn push_front_node(&mut self, node: NonNull<Node<T>>) {         // SAFETY: This method takes care not to create mutable references to@@ -213,8 +213,8 @@ impl<T, A: Allocator> LinkedList<T, A> {     /// Adds the given node to the back of the list.     ///     /// # Safety-    /// `node` must point to a valid node in the list's allocator.-    /// This method takes ownership of the node, so the pointer should not be used again.+    ///+    /// `node` must point to a valid owned node in the list's allocator.     #[inline]     unsafe fn push_back_node(&mut self, node: NonNull<Node<T>>) {         // SAFETY: This method takes care not to create mutable references to@@ -257,25 +257,27 @@ impl<T, A: Allocator> LinkedList<T, A> {      /// Unlinks the specified node from the current list.     ///-    /// Warning: this will not check that the provided node belongs to the current list.-    ///     /// This method takes care not to create mutable references to `element`, to     /// maintain validity of aliasing pointers.+    ///+    /// # Safety+    ///+    /// The provided node must belong to the current list.     #[inline]     unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {         // SAFETY: This is ours now, we can create a &mut.         let node = unsafe { node.as_mut() };          // Not creating new mutable (unique!) references overlapping `element`.         match node.prev {-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `prev` is a live node in this list.             Some(prev) => unsafe { (*prev.as_ptr()).next = node.next },             // this node is the head node             None => self.head = node.next,         };          match node.next {-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `next` is a live node in this list.             Some(next) => unsafe { (*next.as_ptr()).prev = node.prev },             // this node is the tail node             None => self.tail = node.prev,@@ -286,7 +288,14 @@ impl<T, A: Allocator> LinkedList<T, A> {      /// Splices a series of nodes between two existing nodes.     ///-    /// Warning: this will not check that the provided node belongs to the two existing lists.+    /// # Safety+    ///+    /// * The provided nodes must belong to the two existing lists.+    /// * `splice_length` must be exactly the number of nodes between `splice_start` and `splice_end`, inclusive.+    /// * `splice_start` and `splice_end` must be in the same list, and `splice_start` must precede `splice_end`.+    /// * If `existing_prev` is `None`, then `existing_next` must be the head node in `self`.+    ///   If `existing_next` is `None`, then `existing_prev` must be the end node in `self`.+    ///   In other case, `existing_prev` must be the predecessor of `existing_next` in `self`.     #[inline]     unsafe fn splice_nodes(         &mut self,@@ -299,22 +308,23 @@ impl<T, A: Allocator> LinkedList<T, A> {         // This method takes care not to create multiple mutable references to whole nodes at the same time,         // to maintain validity of aliasing pointers into `element`.         if let Some(mut existing_prev) = existing_prev {-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `existing_prev` points to a live node owned by `self`, which don't have any other mutable references.             unsafe {                 existing_prev.as_mut().next = Some(splice_start);             }         } else {             self.head = Some(splice_start);         }         if let Some(mut existing_next) = existing_next {-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `existing_next` points to a live node owned by `self`, which don't have any other mutable references.             unsafe {                 existing_next.as_mut().prev = Some(splice_end);             }         } else {             self.tail = Some(splice_end);         }-        // ignore-tidy-undocumented-unsafe+        // SAFETY: This method takes care not to create multiple mutable references to whole nodes at the same time,+        // to maintain validity of aliasing pointers into `element`.         unsafe {             splice_start.as_mut().prev = existing_prev;             splice_end.as_mut().next = existing_next;@@ -340,6 +350,16 @@ impl<T, A: Allocator> LinkedList<T, A> {         }     } +    /// Splits this list before `split_node`.+    ///+    /// `self` retains `split_node` and all nodes after it, while the returned list contains all+    /// nodes before `split_node`. If `split_node` is `None`, all nodes are moved into the returned+    /// list and `self` is left empty.+    ///+    /// # Safety+    ///+    /// * If `split_node` is `Some`, it must point to a node in `self`.+    /// * If `split_node` is `Some`, `at` must equal its zero-based index in `self`.     #[inline]     unsafe fn split_off_before_node(         &mut self,@@ -353,12 +373,12 @@ impl<T, A: Allocator> LinkedList<T, A> {         if let Some(mut split_node) = split_node {             let first_part_head;             let first_part_tail;-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `split_node` points to a live node in `self`, which don't have any other mutable references.             unsafe {                 first_part_tail = split_node.as_mut().prev.take();             }             if let Some(mut tail) = first_part_tail {-                // ignore-tidy-undocumented-unsafe+                // SAFETY: `tail` is the live predecessor of `split_node`, which don't have any other mutable references.                 unsafe {                     tail.as_mut().next = None;                 }@@ -385,6 +405,16 @@ impl<T, A: Allocator> LinkedList<T, A> {         }     } +    /// Splits this list after `split_node`.+    ///+    /// `self` retains `split_node` and all nodes before it, while the returned list contains all+    /// nodes after `split_node`. If `split_node` is `None`, all nodes are moved into the returned+    /// list and `self` is left empty.+    ///+    /// # Safety+    ///+    /// * If `split_node` is `Some`, it must point to a node in `self`.+    /// * If `split_node` is `Some`, `at` must equal its zero-based index in `self` plus one.     #[inline]     unsafe fn split_off_after_node(         &mut self,@@ -399,12 +429,12 @@ impl<T, A: Allocator> LinkedList<T, A> {         if let Some(mut split_node) = split_node {             let second_part_head;             let second_part_tail;-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `split_node` points to a live node in `self`, which don't have any other mutable references.             unsafe {                 second_part_head = split_node.as_mut().next.take();             }             if let Some(mut head) = second_part_head {-                // ignore-tidy-undocumented-unsafe+                // SAFETY: `head` is the live successor of `split_node`, which don't have any other mutable references.                 unsafe {                     head.as_mut().prev = None;                 }@@ -755,7 +785,7 @@ impl<T, A: Allocator> LinkedList<T, A> {     #[stable(feature = "rust1", since = "1.0.0")]     #[rustc_confusables("first")]     pub fn front(&self) -> Option<&T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `self` is immutable borrowed, so the head node can be immutable borrowed as well.         unsafe { self.head.as_ref().map(|node| &node.as_ref().element) }     } @@ -785,7 +815,7 @@ impl<T, A: Allocator> LinkedList<T, A> {     #[must_use]     #[stable(feature = "rust1", since = "1.0.0")]     pub fn front_mut(&mut self) -> Option<&mut T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `self` is mutable borrowed, so the head node can be mutable borrowed as well.         unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) }     } @@ -809,7 +839,7 @@ impl<T, A: Allocator> LinkedList<T, A> {     #[must_use]     #[stable(feature = "rust1", since = "1.0.0")]     pub fn back(&self) -> Option<&T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `self` is immutable borrowed, so the tail node can be immutable borrowed as well.         unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) }     } @@ -838,7 +868,7 @@ impl<T, A: Allocator> LinkedList<T, A> {     #[inline]     #[stable(feature = "rust1", since = "1.0.0")]     pub fn back_mut(&mut self) -> Option<&mut T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `self` is mutable borrowed, so the tail node can be mutable borrowed as well.         unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) }     } @@ -1040,7 +1070,7 @@ impl<T, A: Allocator> LinkedList<T, A> {             }             iter.tail         };-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `split_node` is a valid node in `self`, and `at` is `index_of(split_node) + 1`.         unsafe { self.split_off_after_node(split_node, at) }     } @@ -1444,7 +1474,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {                 self.index = 0;             }             // We had a previous element, so let's go to its next-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `current` is a pointer to a live node in `list`, which don't have mutable reference.             Some(current) => unsafe {                 self.current = current.as_ref().next;                 self.index += 1;@@ -1466,7 +1496,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {                 self.index = self.list.len().saturating_sub(1);             }             // Have a prev. Yield it and go to the previous element.-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `current` is a pointer to a live node in `list`, which don't have mutable reference.             Some(current) => unsafe {                 self.current = current.as_ref().prev;                 self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());@@ -1482,7 +1512,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {     #[must_use]     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn current(&self) -> Option<&'a T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`.         unsafe { self.current.map(|current| &(*current.as_ptr()).element) }     } @@ -1494,7 +1524,9 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {     #[must_use]     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn peek_next(&self) -> Option<&'a T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`,+        // and `current` does not have mutable reference.+        // If `next` is `Some`, then we can get inner pointer which points at a live node in `list`.         unsafe {             let next = match self.current {                 None => self.list.head,@@ -1512,7 +1544,9 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {     #[must_use]     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn peek_prev(&self) -> Option<&'a T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`,+        // and `current` does not have mutable reference.+        // If `prev` is `Some`, then we can get inner pointer which points at a live node in `list`.         unsafe {             let prev = match self.current {                 None => self.list.tail,@@ -1576,7 +1610,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {                 self.index = 0;             }             // We had a previous element, so let's go to its next-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `current` is a pointer to a live node in `list`, which don't have mutable reference.             Some(current) => unsafe {                 self.current = current.as_ref().next;                 self.index += 1;@@ -1598,7 +1632,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {                 self.index = self.list.len().saturating_sub(1);             }             // Have a prev. Yield it and go to the previous element.-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `current` is a pointer to a live node in `list`, which don't have mutable reference.             Some(current) => unsafe {                 self.current = current.as_ref().prev;                 self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len());@@ -1614,7 +1648,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     #[must_use]     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn current(&mut self) -> Option<&mut T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`.         unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) }     } @@ -1625,7 +1659,9 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     /// element of the `LinkedList` then this returns `None`.     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn peek_next(&mut self) -> Option<&mut T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`,+        // and `current` does not have mutable reference.+        // If `next` is `Some`, then we can get inner pointer which points at a live node in `list`.         unsafe {             let next = match self.current {                 None => self.list.head,@@ -1642,7 +1678,9 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     /// element of the `LinkedList` then this returns `None`.     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn peek_prev(&mut self) -> Option<&mut T> {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, then `current` is a pointer to a live node in `list`,+        // and `current` does not have mutable reference.+        // If `prev` is `Some`, then we can get inner pointer which points at a live node in `list`.         unsafe {             let prev = match self.current {                 None => self.list.tail,@@ -1688,7 +1726,15 @@ impl<'a, T> CursorMut<'a, T> {         let Some((splice_head, splice_tail, splice_len)) = list.detach_all_nodes() else {             return;         };-        // ignore-tidy-undocumented-unsafe+        // SAFETY:+        // * If `self.current` is `Some`, then `node` is a pointer to a live node in `list`+        //   and don't have mutable reference.+        // * `self.current` (possible `None`) and `node_next` belong to `self.list`,+        //   while `splice_head` and `splice_tail` belong to `list`.+        // * `splice_len` is the length of the new nodes to be spliced in.+        // * `splice_head` and `splice_tail` are the head and tail of the new nodes to be spliced in.+        // * If `self.current` is `None`, then `node_next` is the head of the list.+        //   If `self.current` is `Some`, then `node_next` is the next node after `self.current`.         unsafe {             let node_next = match self.current {                 None => self.list.head,@@ -1712,7 +1758,15 @@ impl<'a, T> CursorMut<'a, T> {             Some(parts) => parts,             _ => return,         };-        // ignore-tidy-undocumented-unsafe+        // SAFETY:+        // * If `self.current` is `Some`, then `node` is a pointer to a live node in `list`+        //   and don't have mutable reference.+        // * `self.current` (possible `None`) and `node_prev` belong to `self.list`,+        //   while `splice_head` and `splice_tail` belong to `list`.+        // * `splice_len` is the length of the new nodes to be spliced in.+        // * `splice_head` and `splice_tail` are the head and tail of the new nodes to be spliced in.+        // * If `self.current` is `None`, then `node_prev` is the tail of the list.+        //   If `self.current` is `Some`, then `node_prev` is the previous node before `self.current`.         unsafe {             let node_prev = match self.current {                 None => self.list.tail,@@ -1733,7 +1787,15 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     pub fn insert_after(&mut self, item: T) {         let spliced_node =             Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0;-        // ignore-tidy-undocumented-unsafe+        // SAFETY:+        // * If `self.current` is `Some`, then `node` is a pointer to a live node in `list`+        //   and don't have mutable reference.+        // * `self.current` (possible `None`) and `node_next` belong to `self.list`,+        //   while `spliced_node` does not belong to any list.+        // * This method only inserts one node, so `spliced_node` is both the head and tail of the new nodes to be spliced in.+        // * The length of the new nodes to be spliced in is 1.+        // * If `self.current` is `None`, then `node_next` is the head of the list.+        //   If `self.current` is `Some`, then `node_next` is the next node after `self.current`.         unsafe {             let node_next = match self.current {                 None => self.list.head,@@ -1755,7 +1817,15 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     pub fn insert_before(&mut self, item: T) {         let spliced_node =             Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0;-        // ignore-tidy-undocumented-unsafe+        // SAFETY:+        // * If `self.current` is `Some`, then `node` is a pointer to a live node in `list`+        //   and don't have mutable reference.+        // * `self.current` (possible `None`) and `node_prev` belong to `self.list`,+        //   while `spliced_node` does not belong to any list.+        // * This method only inserts one node, so `spliced_node` is both the head and tail of the new nodes to be spliced in.+        // * The length of the new nodes to be spliced in is 1.+        // * If `self.current` is `None`, then `node_prev` is the tail of the list.+        //   If `self.current` is `Some`, then `node_prev` is the previous node before `self.current`.         unsafe {             let node_prev = match self.current {                 None => self.list.tail,@@ -1776,7 +1846,8 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     #[unstable(feature = "linked_list_cursors", issue = "58533")]     pub fn remove_current(&mut self) -> Option<T> {         let unlinked_node = self.current?;-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `unlinked_node` is a pointer to a live node owned by `self.list`.+        // It is safe to unlink it and construct a `Box` from it.         unsafe {             self.current = unlinked_node.as_ref().next;             self.list.unlink_node(unlinked_node);@@ -1798,7 +1869,8 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {         A: AllocatorClone,     {         let mut unlinked_node = self.current?;-        // ignore-tidy-undocumented-unsafe+        // SAFETY: `unlinked_node` is a pointer to a live node owned by `self.list`.+        // It is safe to unlink it. Also, `unlinked_node` does not have any mutable reference.         unsafe {             self.current = unlinked_node.as_ref().next;             self.list.unlink_node(unlinked_node);@@ -1831,7 +1903,8 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {             // The "ghost" non-element's index has changed to 0.             self.index = 0;         }-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, it contains a pointer to a live node in `list`,+        // and `split_off_idx` is `self.index + 1`.         unsafe { self.list.split_off_after_node(self.current, split_off_idx) }     } @@ -1848,7 +1921,8 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {     {         let split_off_idx = self.index;         self.index = 0;-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `self.current` is `Some`, it contains a pointer to a live node in `list`,+        // and `split_off_idx` is the index of `self.current`.         unsafe { self.list.split_off_before_node(self.current, split_off_idx) }     } @@ -2020,7 +2094,7 @@ where      fn next(&mut self) -> Option<T> {         while let Some(mut node) = self.it {-            // ignore-tidy-undocumented-unsafe+            // SAFETY: `node` is a pointer to a live node in `list`, which don't have mutable reference.             unsafe {                 self.it = node.as_ref().next;                 self.idx += 1;@@ -2048,7 +2122,7 @@ where     A: Allocator, {     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {-        // ignore-tidy-undocumented-unsafe+        // SAFETY: If `node` is `Some`, then `node` is a pointer to a live node in `list`.         let peek = self.it.map(|node| unsafe { &node.as_ref().element });         f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive()     }
src/etc/lldb_lookup.py31 + / 30 −
@@ -1,50 +1,51 @@ from __future__ import annotations-from typing import TYPE_CHECKING, List, Callable -import lldb+from typing import TYPE_CHECKING, Callable, List +import lldb from lldb_providers import (-    LLDBFeature,     FEATURE_FLAGS,-    LLDBOpaque,-    StructSyntheticProvider,-    StdHashMapSyntheticProvider,-    StdOldHashMapSyntheticProvider,-    StdRcSyntheticProvider,-    TupleSyntheticProvider,-    EmptySyntheticProvider,     ClangEncodedEnumProvider,+    ClangEncodedEnumSummaryProvider,     DefaultSyntheticProvider,-    StdStringSyntheticProvider,-    StdStringSummaryProvider,-    StdSliceSyntheticProvider,-    StdStrSummaryProvider,+    EmptySyntheticProvider,+    LLDBFeature,+    LLDBOpaque,+    MSVCEnumSummaryProvider,+    MSVCEnumSyntheticProvider,+    MSVCStdSliceSyntheticProvider,     MSVCStrSyntheticProvider,+    MSVCTupleSyntheticProvider,     SizeSummaryProvider,-    MSVCStdSliceSyntheticProvider,-    StdSliceSummaryProvider,-    StdOsStringSummaryProvider,-    StdVecSyntheticProvider,-    StdVecDequeSyntheticProvider,-    StdRcSummaryProvider,     StdCellSyntheticProvider,-    StdRefSyntheticProvider,-    StdRefSummaryProvider,+    StdHashMapSyntheticProvider,     StdNonZeroNumberSummaryProvider,+    StdOldHashMapSyntheticProvider,+    StdOsStringSummaryProvider,     StdPathBufSummaryProvider,     StdPathSummaryProvider,-    MSVCEnumSyntheticProvider,-    MSVCEnumSummaryProvider,-    TupleSummaryProvider,-    MSVCTupleSyntheticProvider,-    ClangEncodedEnumSummaryProvider,+    StdRcSummaryProvider,+    StdRcSyntheticProvider,+    StdRefSummaryProvider,+    StdRefSyntheticProvider,+    StdSliceSummaryProvider,+    StdSliceSyntheticProvider,+    StdStringSummaryProvider,+    StdStringSyntheticProvider,+    StdStrSummaryProvider,+    StdVecDequeSyntheticProvider,+    StdVecSyntheticProvider,     StructSummaryProvider,+    StructSyntheticProvider,+    TupleSummaryProvider,+    TupleSyntheticProvider,     f16SummaryProvider,     f128SummaryProvider,-    # re-exports-    get_template_args as get_template_args,-    resolve_msvc_template_arg as resolve_msvc_template_arg, )++# re-exports+from lldb_providers import get_template_args as get_template_args+from lldb_providers import resolve_msvc_template_arg as resolve_msvc_template_arg from rust_types import (     ENUM_DISR_FIELD_NAME,     ENUM_LLDB_ENCODED_VARIANTS,
src/etc/lldb_providers.py105 + / 94 −
@@ -2,7 +2,7 @@  import sys from enum import Flag, auto-from typing import TYPE_CHECKING, Dict, Generator, List, Optional+from typing import TYPE_CHECKING, ClassVar, Dict, Generator, List, Optional  from lldb import (     SBData,@@ -363,7 +363,7 @@ def TupleSummaryProvider(valobj: SBValue, _dict: LLDBOpaque):   def aggregate_field_summary(valobj: SBValue, _dict) -> Generator[str, None, None]:-    for i in range(0, valobj.GetNumChildren()):+    for i in range(valobj.GetNumChildren()):         child: SBValue = valobj.GetChildAtIndex(i)         summary = child.summary         if summary is None:@@ -544,7 +544,7 @@ def sequence_formatter(output: str, valobj: SBValue, _dict: LLDBOpaque):         return output      long: bool = False-    for i in range(0, length):+    for i in range(length):         if len(output) > 32:             long = True             break@@ -612,6 +612,8 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         ptr_size = valobj.GetTarget().GetAddressByteSize() * 8         self.no_hi_bit_max = 1 << (ptr_size - 1) +        self.element_type = valobj.GetType().GetBasicType(eBasicTypeUnsignedChar)+         self.update()      def update(self):@@ -640,8 +642,6 @@ def update(self):         else:             self.length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() -        self.element_type = self.data_ptr.GetType().GetPointeeType()-     def has_children(self) -> bool:         return True @@ -668,16 +668,28 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:   class MSVCStrSyntheticProvider:-    _name_map: Dict[str, str] = {+    _name_map: ClassVar[Dict[str, str]] = {         "ref$<str$>": "&str",         "ref_mut$<str$>": "&mut str",         "ptr_const$<str$>": "*const str",         "ptr_mut$<str$>": "*mut str",     }-    __slots__ = ["data_ptr", "length", "valobj"]+    __slots__ = ("data_ptr", "length", "type_name", "valobj")++    @staticmethod+    def _normalize_type_name(name: str):+        if (type_name := MSVCStrSyntheticProvider._name_map.get(name)) is not None:+            return type_name+        # we use `startswith` instead of an exact match because we don't know for sure which+        # allocator is being used+        elif name.startswith("alloc::boxed::Box<str$"):+            return "Box<str>"+        else:+            return name      def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.valobj = valobj+        self.type_name = self._normalize_type_name(self.valobj.GetTypeName())         self.update()      def update(self):@@ -711,14 +723,7 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:         return element      def get_type_name(self):-        name = self.valobj.GetTypeName()--        if (type_name := self._name_map.get(name)) is not None:-            return type_name-        elif name.startswith("alloc::boxed::Box<str$"):-            return "Box<str>"-        else:-            return name+        return self.type_name   def _getVariantName(variant: SBValue) -> str:@@ -745,7 +750,7 @@ class ClangEncodedEnumProvider:     DISCRIMINANT_MEMBER_NAME = "$discr$"     VALUE_MEMBER_NAME = "value" -    __slots__ = ("valobj", "variant", "value")+    __slots__ = ("valobj", "value", "variant")      def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.valobj = valobj@@ -819,39 +824,55 @@ class MSVCEnumSyntheticProvider:     valobj: SBValue     variant: SBValue     value: SBValue+    type_name: str++    __slots__ = ("type_name", "valobj", "value", "variant")++    @staticmethod+    def _normalize_type_name(name: str) -> str:+        # remove "enum2$<", str.removeprefix() is python 3.9++        name = name[7:] -    __slots__ = ["valobj", "variant", "value"]+        # MSVC misinterprets ">>" as a shift operator, so spaces are inserted by rust to+        # avoid that+        if name.endswith(" >"):+            name = name[:-2]+        elif name.endswith(">"):+            name = name[:-1]++        return name      def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.valobj = valobj         # This allows the summary provider to still print something         # even if we can't find the variant for whatever reason         self.variant = valobj         self.value = valobj+        self.type_name = self._normalize_type_name(self.valobj.GetTypeName())         self.update()      def update(self):-        tag: SBValue = self.valobj.GetChildMemberWithName("tag")--        if tag.IsValid():-            tag: int = tag.GetValueAsUnsigned()+        if LLDBFeature.StaticFields not in FEATURE_FLAGS:+            # LLDB versions prior to 19.0.0 do not have the `SBTypeGetStaticField` API.+            # With current DI generation there's not a great way to provide a "best effort"+            # evaluation either, so we just return the object itself with no further+            # attempts to inspect the type information+            self.variant = self.valobj+            self.value = self.valobj+            return++        tag_val: SBValue = self.valobj.GetChildMemberWithName("tag")++        if tag_val.IsValid():+            tag: int = tag_val.GetValueAsUnsigned()             for child in self.valobj.GetNonSyntheticValue().children:                 if not child.name.startswith("variant"):                     continue                  variant_type: SBType = child.GetType()-                try:-                    exact: SBTypeStaticField = variant_type.GetStaticFieldWithName(-                        "DISCR_EXACT"-                    )-                except AttributeError:-                    # LLDB versions prior to 19.0.0 do not have the `SBTypeGetStaticField` API.-                    # With current DI generation there's not a great way to provide a "best effort"-                    # evaluation either, so we just return the object itself with no further-                    # attempts to inspect the type information-                    self.variant = self.valobj-                    self.value = self.valobj-                    return+                exact: SBTypeStaticField = variant_type.GetStaticFieldWithName(+                    "DISCR_EXACT"+                )                  if exact.IsValid():                     discr: int = exact.GetConstantValue(@@ -908,12 +929,12 @@ def update(self):                     continue                  variant_type: SBType = child.GetType()-                exact_lo: SBTypeStaticField = variant_type.GetStaticFieldWithName(+                exact_lo_field: SBTypeStaticField = variant_type.GetStaticFieldWithName(                     "DISCR128_EXACT_LO"                 ) -                if exact_lo.IsValid():-                    exact_lo: int = exact_lo.GetConstantValue(+                if exact_lo_field.IsValid():+                    exact_lo: int = exact_lo_field.GetConstantValue(                         self.valobj.target                     ).GetValueAsUnsigned()                     exact_hi: int = (@@ -984,18 +1005,7 @@ def has_children(self) -> bool:         return self.value.MightHaveChildren()      def get_type_name(self) -> str:-        name = self.valobj.GetTypeName()-        # remove "enum2$<", str.removeprefix() is python 3.9+-        name = name[7:]--        # MSVC misinterprets ">>" as a shift operator, so spaces are inserted by rust to-        # avoid that-        if name.endswith(" >"):-            name = name[:-2]-        elif name.endswith(">"):-            name = name[:-1]--        return name+        return self.type_name   def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:@@ -1005,14 +1015,15 @@ def MSVCEnumSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:     variant_names: SBType = valobj.target.FindFirstType(         f"{enum_synth.valobj.GetTypeName()}::VariantNames"     )-    try:++    if LLDBFeature.StaticFields in FEATURE_FLAGS:         name_idx = (             enum_synth.variant.GetType()             .GetStaticFieldWithName("NAME")             .GetConstantValue(valobj.target)             .GetValueAsUnsigned()         )-    except AttributeError:+    else:         # LLDB versions prior to 19 do not have the `SBTypeGetStaticField` API, and have no way         # to determine the value based on the tag field.         tag: SBValue = valobj.GetChildMemberWithName("tag")@@ -1082,10 +1093,13 @@ def has_children(self) -> bool:   class MSVCTupleSyntheticProvider:-    __slots__ = ["valobj"]+    __slots__ = ("type_name", "valobj")      def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.valobj = valobj+        type_name = self.valobj.GetTypeName()+        # remove "tuple$<" and ">", str.removeprefix and str.removesuffix require python 3.9++        self.type_name = f"({type_name[7:-1].strip()})"      def num_children(self) -> int:         return self.valobj.GetNumChildren()@@ -1108,10 +1122,7 @@ def has_children(self) -> bool:         return self.valobj.MightHaveChildren()      def get_type_name(self) -> str:-        name = self.valobj.GetTypeName()-        # remove "tuple$<" and ">", str.removeprefix and str.removesuffix require python 3.9+-        name = name[7:-1].strip()-        return "(" + name + ")"+        return self.type_name   class StdVecSyntheticProvider:@@ -1138,6 +1149,17 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.element_type = None         ptr_size = valobj.GetTarget().GetAddressByteSize() * 8         self.no_hi_bit_max = 1 << (ptr_size - 1)++        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)++        if not self.element_type.IsValid():+            arg_name = next(get_template_args(self.valobj.GetTypeName()))++            self.element_type = resolve_msvc_template_arg(+                arg_name, self.valobj.GetTarget()+            )++        self.element_type_size = self.element_type.GetByteSize()         self.update()      def num_children(self) -> int:@@ -1154,7 +1176,7 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:         start = self.data_ptr.GetValueAsUnsigned()         address = start + index * self.element_type_size         element = self.data_ptr.CreateValueFromAddress(-            "[%s]" % index, address, self.element_type+            f"[{index}]", address, self.element_type         )         return element @@ -1172,28 +1194,19 @@ def update(self):         else:             self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() -        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)--        if not self.element_type.IsValid():-            arg_name = next(get_template_args(self.valobj.GetTypeName()))--            self.element_type = resolve_msvc_template_arg(arg_name, self.valobj.target)--        self.element_type_size = self.element_type.GetByteSize()-     def has_children(self) -> bool:         return True   class StdSliceSyntheticProvider:-    __slots__ = [-        "valobj",-        "length",+    __slots__ = (         "data_ptr",-        "element_type",         "element_size",+        "element_type",         "is_str",-    ]+        "length",+        "valobj",+    )      def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         self.valobj = valobj@@ -1208,8 +1221,12 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):             "ptr_const$<str>",             "ptr_mut$<str>",         }+         self.update() +        self.element_type = self.data_ptr.GetType().GetPointeeType()+        self.element_size = self.element_type.GetByteSize()+     def num_children(self) -> int:         return self.length @@ -1224,7 +1241,7 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:         start = self.data_ptr.GetValueAsUnsigned()         address = start + index * self.element_size         element = self.data_ptr.CreateValueFromAddress(-            "[%s]" % index, address, self.element_type+            f"[{index}]", address, self.element_type         )          if self.is_str:@@ -1235,9 +1252,6 @@ def update(self):         self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()         self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr") -        self.element_type = self.data_ptr.GetType().GetPointeeType()-        self.element_size = self.element_type.GetByteSize()-     def has_children(self) -> bool:         return True @@ -1299,7 +1313,15 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque):         # logger = Logger.Logger()         # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())         self.valobj = valobj-        self.element_type = None+        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)++        if not self.element_type.IsValid():+            arg_name = next(get_template_args(self.valobj.GetTypeName()))++            self.element_type = resolve_msvc_template_arg(arg_name, self.valobj.target)++        self.element_type_size = self.element_type.GetByteSize()+         self.update()      def num_children(self) -> int:@@ -1316,7 +1338,7 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:         start = self.data_ptr.GetValueAsUnsigned()         address = start + ((index + self.head) % self.cap) * self.element_type_size         element = self.data_ptr.CreateValueFromAddress(-            "[%s]" % index, address, self.element_type+            f"[{index}]", address, self.element_type         )         return element @@ -1339,15 +1361,6 @@ def update(self):             self.buf.GetChildMemberWithName("ptr")         ) -        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)--        if not self.element_type.IsValid():-            arg_name = next(get_template_args(self.valobj.GetTypeName()))--            self.element_type = resolve_msvc_template_arg(arg_name, self.valobj.target)--        self.element_type_size = self.element_type.GetByteSize()-     def has_children(self) -> bool:         return True @@ -1400,14 +1413,14 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:         idx = table_index & self.capacity_mask         address = pairs_start + idx * self.pair_type_size         element = self.data_ptr.CreateValueFromAddress(-            "[%s]" % index, address, self.pair_type+            f"[{index}]", address, self.pair_type         )         if self.show_values:             return element         else:             key = element.GetChildAtIndex(0)             return self.valobj.CreateValueFromData(-                "[%s]" % index, key.GetData(), key.GetType()+                f"[{index}]", key.GetData(), key.GetType()             )      def update(self):@@ -1434,7 +1447,7 @@ def update(self):         for idx in range(self.capacity):             address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size             hash_uint = self.data_ptr.CreateValueFromAddress(-                "[%s]" % idx, address, self.hash_uint_type+                f"[{idx}]", address, self.hash_uint_type             )             hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)             if hash_ptr.GetValueAsUnsigned() != 0:@@ -1471,15 +1484,15 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]:             idx = -(idx + 1)         address = pairs_start + idx * self.pair_type_size         element = self.data_ptr.CreateValueFromAddress(-            "[%s]" % index, address, self.pair_type+            f"[{index}]", address, self.pair_type         )          if self.show_values:             return element         else:             key = element.GetChildAtIndex(0)             return self.valobj.CreateValueFromData(-                "[%s]" % index, key.GetData(), key.GetType()+                f"[{index}]", key.GetData(), key.GetType()             )      def update(self):@@ -1521,7 +1534,7 @@ def update(self):         for idx in range(capacity):             address = ctrl.GetValueAsUnsigned() + idx * u8_type_size             value = ctrl.CreateValueFromAddress(-                "ctrl[%s]" % idx, address, u8_type+                f"ctrl[{idx}]", address, u8_type             ).GetValueAsUnsigned()             is_present = value & 128 == 0             if is_present:@@ -1657,9 +1670,7 @@ def has_children(self) -> bool:  def StdRefSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:     borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()-    return (-        "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)-    )+    return f"borrow={borrow}" if borrow >= 0 else f"borrow_mut={-borrow}"   class StdRefSyntheticProvider:
src/librustdoc/visit_ast.rs1 + / 2 −
@@ -3,7 +3,6 @@  use std::mem; -use rustc_ast::attr::AttributeExt; use rustc_attr_ir::{DocInline, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def::{DefKind, MacroKinds, Res};@@ -282,7 +281,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {             Doc(d)             if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline)         ) || (document_hidden-            && use_attrs.iter().any(|attr| attr.is_doc_hidden()));+            && find_attr!(use_attrs, Doc(rustc_attr_ir::DocAttribute { hidden: Some(_), .. })));          if is_no_inline {             debug!("doc::no_inline or doc::hidden");
src/tools/clippy/clippy_utils/src/attrs.rs5 + / 2 −
@@ -102,8 +102,11 @@ pub fn is_proc_macro(attrs: &[impl AttributeExt]) -> bool { }  /// Checks whether `attrs` contain `#[doc(hidden)]`-pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool {-    attrs.iter().any(AttributeExt::is_doc_hidden)+pub fn is_doc_hidden(attrs: &[rustc_attr_ir::Attribute]) -> bool {+    find_attr!(+        attrs,+        Doc(rustc_attr_ir::DocAttribute { hidden: Some(_), .. })+    ) }  /// Checks whether the given ADT, or any of its fields/variants, are marked as `#[non_exhaustive]`
tests/rustdoc-html/impossible-default.rsremoved0 + / 28 −
@@ -1,28 +0,0 @@-#![crate_name = "foo"]--// Check that default trait items that are impossible to satisfy--pub trait Foo {-    fn needs_sized(&self)-    where-        Self: Sized,-    {}--    fn no_needs_sized(&self) {}-}--//@ !has foo/struct.Bar.html '//*[@id="method.needs_sized"]//h4[@class="code-header"]' \-// "fn needs_sized"-//@ has foo/struct.Bar.html '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' \-// "fn no_needs_sized"-pub struct Bar([u8]);--impl Foo for Bar {}--//@ has foo/struct.Generic.html '//*[@id="method.needs_sized"]//h4[@class="code-header"]' \-// "fn needs_sized"-//@ has foo/struct.Generic.html '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' \-// "fn no_needs_sized"-pub struct Generic<T: ?Sized>(T);--impl<T: ?Sized> Foo for Generic<T> {}
tests/rustdoc-html/trait/auxiliary/unstable-trait.rsrenamed0 + / 0 −

GitHub publishes no diff for this file. View it on GitHub ↗

tests/rustdoc-html/trait/dyn-compatibility.rsrenamed0 + / 0 −

GitHub publishes no diff for this file. View it on GitHub ↗

tests/rustdoc-html/trait/ensure-src-link.rsrenamed0 + / 0 −

GitHub publishes no diff for this file. View it on GitHub ↗

tests/rustdoc-html/trait/final-trait-method.rsrenamed0 + / 0 −

GitHub publishes no diff for this file. View it on GitHub ↗

tests/rustdoc-html/trait/hide-unstable-trait.rsrenamed0 + / 0 −

GitHub publishes no diff for this file. View it on GitHub ↗

tests/rustdoc-html/trait/impossible-default.rsadded28 + / 0 −
@@ -0,0 +1,28 @@+#![crate_name = "foo"]++// Check that default trait items that are impossible to satisfy are not+// listed.++pub trait Foo {+    fn needs_sized(&self)+    where+        Self: Sized,+    {}++    fn no_needs_sized(&self) {}+}++//@ has 'foo/struct.Bar.html'+// "fn needs_sized" should not be listed.+//@ count - '//*[@id="trait-implementations-list"]//h4[@class="code-header"]' 1+//@ has - '//*[@id="trait-implementations-list"]//h4[@class="code-header"]' "fn no_needs_sized"+pub struct Bar([u8]);++impl Foo for Bar {}++//@ has 'foo/struct.Generic.html'+//@ has - '//*[@id="method.needs_sized"]//h4[@class="code-header"]' "fn needs_sized"+//@ has - '//*[@id="method.no_needs_sized"]//h4[@class="code-header"]' "fn no_needs_sized"+pub struct Generic<T: ?Sized>(T);++impl<T: ?Sized> Foo for Generic<T> {}