//! conflicts between multiple such attributes attached to the same
//! item.
-use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
+use rustc_ast::tokenstream::DelimSpan;
+use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MacArgs, MetaItemKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
}
}
+ /// Checks `#[doc(hidden)]` attributes. Returns `true` if valid.
+ fn check_doc_hidden(
+ &self,
+ attr: &Attribute,
+ meta_index: usize,
+ meta: &NestedMetaItem,
+ hir_id: HirId,
+ target: Target,
+ ) -> bool {
+ if let Target::AssocConst
+ | Target::AssocTy
+ | Target::Method(MethodKind::Trait { body: true }) = target
+ {
+ let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
+ let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+
+ if Target::from_item(containing_item) == Target::Impl {
+ let meta_items = attr.meta_item_list().unwrap();
+
+ let (span, replacement_span) = if meta_items.len() == 1 {
+ (attr.span, attr.span)
+ } else {
+ let meta_span = meta.span();
+ (
+ meta_span,
+ meta_span.until(match meta_items.get(meta_index + 1) {
+ Some(next_item) => next_item.span(),
+ None => match attr.get_normal_item().args {
+ MacArgs::Delimited(DelimSpan { close, .. }, ..) => close,
+ _ => unreachable!(),
+ },
+ }),
+ )
+ };
+
+ // FIXME: #[doc(hidden)] was previously erroneously allowed on trait impl items,
+ // so for backward compatibility only emit a warning and do not mark it as invalid.
+ self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| {
+ lint.build("`#[doc(hidden)]` is ignored on trait impl items")
+ .warn(
+ "this was previously accepted by the compiler but is \
+ being phased out; it will become a hard error in \
+ a future release!",
+ )
+ .note(
+ "whether the impl item is `doc(hidden)` or not \
+ entirely depends on the corresponding trait item",
+ )
+ .span_suggestion(
+ replacement_span,
+ "remove this attribute",
+ String::new(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ });
+ }
+ }
+
+ true
+ }
+
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
fn check_attr_not_crate_level(
&self,
let mut is_valid = true;
if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() {
- for meta in list {
+ for (meta_index, meta) in list.into_iter().enumerate() {
if let Some(i_meta) = meta.meta_item() {
match i_meta.name_or_empty() {
sym::alias
is_valid = false;
}
+ sym::hidden if !self.check_doc_hidden(attr,
+ meta_index,
+ meta,
+ hir_id,
+ target,
+ ) => {
+ is_valid = false;
+ }
+
// no_default_passes: deprecated
// passes: deprecated
// plugins: removed, but rustdoc warns about it itself
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
self.len()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
$(
#[unstable(feature = "convert_float_to_int", issue = "67057")]
impl FloatToInt<$Int> for $Float {
- #[doc(hidden)]
#[inline]
unsafe fn to_int_unchecked(self) -> $Int {
// SAFETY: the safety contract must be upheld by the caller.
self.it.map(T::clone).fold(init, f)
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
where
Self: TrustedRandomAccessNoCoerce,
self.it.advance_by(n)
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
where
Self: TrustedRandomAccessNoCoerce,
}
#[rustc_inherit_overflow_checks]
- #[doc(hidden)]
#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
where
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
self.iter.fold(init, map_fold(self.f, g))
}
- #[doc(hidden)]
#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
where
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
}
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: since the caller guarantees that `i` is in bounds,
// which means that `i` cannot overflow an `isize`, and the
}
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: the caller guarantees that `i` is in bounds,
}
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: see comments for `Chunks::__iterator_get_unchecked`.
self.next_back()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: mostly identical to `Chunks::__iterator_get_unchecked`.
self.next_back()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: see comments for `ChunksMut::__iterator_get_unchecked`.
self.iter.last()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a [T; N] {
// SAFETY: The safety guarantees of `__iterator_get_unchecked` are
// transferred to the caller.
self.iter.last()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> &'a mut [T; N] {
// SAFETY: The safety guarantees of `__iterator_get_unchecked` are transferred to
// the caller.
}
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = match end.checked_sub(self.chunk_size) {
}
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = match end.checked_sub(self.chunk_size) {
self.next_back()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = end - self.chunk_size;
self.next_back()
}
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = end - self.chunk_size;
None
}
- #[doc(hidden)]
#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
// SAFETY: the caller must guarantee that `i` is in bounds of
}
#[inline]
- #[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 {
// SAFETY: the caller must uphold the safety contract
// for `Iterator::__iterator_get_unchecked`.
--- /dev/null
+#![deny(unused_attributes)]
+#![crate_type = "lib"]
+// run-rustfix
+
+pub trait Trait {
+ type It;
+ const IT: ();
+ fn it0();
+ fn it1();
+ fn it2();
+}
+
+pub struct Implementor;
+
+impl Trait for Implementor {
+
+ type It = ();
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+
+ const IT: () = ();
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(alias = "aka")]
+ fn it0() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(alias = "this", )]
+ fn it1() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc()]
+ fn it2() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+ //~| ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+}
--- /dev/null
+#![deny(unused_attributes)]
+#![crate_type = "lib"]
+// run-rustfix
+
+pub trait Trait {
+ type It;
+ const IT: ();
+ fn it0();
+ fn it1();
+ fn it2();
+}
+
+pub struct Implementor;
+
+impl Trait for Implementor {
+ #[doc(hidden)]
+ type It = ();
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(hidden)]
+ const IT: () = ();
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(hidden, alias = "aka")]
+ fn it0() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(alias = "this", hidden,)]
+ fn it1() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+
+ #[doc(hidden, hidden)]
+ fn it2() {}
+ //~^^ ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+ //~| ERROR `#[doc(hidden)]` is ignored
+ //~| WARNING this was previously accepted
+}
--- /dev/null
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:16:5
+ |
+LL | #[doc(hidden)]
+ | ^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: the lint level is defined here
+ --> $DIR/unused-attr-doc-hidden.rs:1:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:21:5
+ |
+LL | #[doc(hidden)]
+ | ^^^^^^^^^^^^^^ help: remove this attribute
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:26:11
+ |
+LL | #[doc(hidden, alias = "aka")]
+ | ^^^^^^--
+ | |
+ | help: remove this attribute
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:31:27
+ |
+LL | #[doc(alias = "this", hidden,)]
+ | ^^^^^^-
+ | |
+ | help: remove this attribute
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:36:11
+ |
+LL | #[doc(hidden, hidden)]
+ | ^^^^^^--
+ | |
+ | help: remove this attribute
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: `#[doc(hidden)]` is ignored on trait impl items
+ --> $DIR/unused-attr-doc-hidden.rs:36:19
+ |
+LL | #[doc(hidden, hidden)]
+ | ^^^^^^ help: remove this attribute
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: whether the impl item is `doc(hidden)` or not entirely depends on the corresponding trait item
+
+error: aborting due to 6 previous errors
+