diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef31d7a4723e8..f15a9fcd59124 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 }} diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 780e1b43412a6..754859793bd33 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -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; - /// 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; diff --git a/compiler/rustc_attr_ir/src/attr.rs b/compiler/rustc_attr_ir/src/attr.rs index e541f1e33eedd..3498bb3b90a33 100644 --- a/compiler/rustc_attr_ir/src/attr.rs +++ b/compiler/rustc_attr_ir/src/attr.rs @@ -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()) } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index c9e58957ebfae..a442c62819c8d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -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 { - fn try_cast_slice(slice: &[T]) -> Option<&[U]> { - use std::any::TypeId; - if TypeId::of::() == TypeId::of::() { - // SAFETY: T == U, so it is sound to cast `&[T]` to `&[U]` - unsafe { - Some(core::slice::from_raw_parts(slice.as_ptr().cast::(), 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; diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1d0cfa59d04fa..bb6c5db0f374b 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -168,8 +168,8 @@ impl LinkedList { /// 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>) { // SAFETY: This method takes care not to create mutable references to @@ -213,8 +213,8 @@ impl LinkedList { /// 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>) { // SAFETY: This method takes care not to create mutable references to @@ -257,10 +257,12 @@ impl LinkedList { /// 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>) { // SAFETY: This is ours now, we can create a &mut. @@ -268,14 +270,14 @@ impl LinkedList { // 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 LinkedList { /// 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,7 +308,7 @@ impl LinkedList { // 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); } @@ -307,14 +316,15 @@ impl LinkedList { 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 LinkedList { } } + /// 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 LinkedList { 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 LinkedList { } } + /// 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 LinkedList { 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 LinkedList { #[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 LinkedList { #[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 LinkedList { #[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 LinkedList { #[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 LinkedList { } 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 { 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 { 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() } diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index 94ed47af1891f..957b8bb557f34 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -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, diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 1bb4883db8de2..4e0452d4cf77b 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -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", "ref_mut$": "&mut str", "ptr_const$": "*const str", "ptr_mut$": "*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" + 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" - 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,8 +824,23 @@ 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 @@ -828,30 +848,31 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque): # 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$", "ptr_mut$", } + 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,7 +1484,7 @@ 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: @@ -1479,7 +1492,7 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]: 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: diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 33b0334e3fd5d..cf294f50b785b 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -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"); diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 88f4cb9ce5cbc..09b37e35244c8 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -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]` diff --git a/tests/rustdoc-html/impossible-default.rs b/tests/rustdoc-html/impossible-default.rs deleted file mode 100644 index c9444004d5c75..0000000000000 --- a/tests/rustdoc-html/impossible-default.rs +++ /dev/null @@ -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); - -impl Foo for Generic {} diff --git a/tests/rustdoc-html/auxiliary/unstable-trait.rs b/tests/rustdoc-html/trait/auxiliary/unstable-trait.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/unstable-trait.rs rename to tests/rustdoc-html/trait/auxiliary/unstable-trait.rs diff --git a/tests/rustdoc-html/dyn-compatibility.rs b/tests/rustdoc-html/trait/dyn-compatibility.rs similarity index 100% rename from tests/rustdoc-html/dyn-compatibility.rs rename to tests/rustdoc-html/trait/dyn-compatibility.rs diff --git a/tests/rustdoc-html/ensure-src-link.rs b/tests/rustdoc-html/trait/ensure-src-link.rs similarity index 100% rename from tests/rustdoc-html/ensure-src-link.rs rename to tests/rustdoc-html/trait/ensure-src-link.rs diff --git a/tests/rustdoc-html/final-trait-method.rs b/tests/rustdoc-html/trait/final-trait-method.rs similarity index 100% rename from tests/rustdoc-html/final-trait-method.rs rename to tests/rustdoc-html/trait/final-trait-method.rs diff --git a/tests/rustdoc-html/hide-unstable-trait.rs b/tests/rustdoc-html/trait/hide-unstable-trait.rs similarity index 100% rename from tests/rustdoc-html/hide-unstable-trait.rs rename to tests/rustdoc-html/trait/hide-unstable-trait.rs diff --git a/tests/rustdoc-html/trait/impossible-default.rs b/tests/rustdoc-html/trait/impossible-default.rs new file mode 100644 index 0000000000000..03b70f2016610 --- /dev/null +++ b/tests/rustdoc-html/trait/impossible-default.rs @@ -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); + +impl Foo for Generic {}