rust-lang/rust · #164964
Rollup of 5 pull requests
.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> {}