|
4 | 4 | //! conflicts between multiple such attributes attached to the same
|
5 | 5 | //! item.
|
6 | 6 |
|
7 |
| -use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; |
| 7 | +use rustc_ast::tokenstream::DelimSpan; |
| 8 | +use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MacArgs, MetaItemKind, NestedMetaItem}; |
8 | 9 | use rustc_data_structures::fx::FxHashMap;
|
9 | 10 | use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
|
10 | 11 | use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
@@ -810,6 +811,68 @@ impl CheckAttrVisitor<'_> {
|
810 | 811 | }
|
811 | 812 | }
|
812 | 813 |
|
| 814 | + /// Checks `#[doc(hidden)]` attributes. Returns `true` if valid. |
| 815 | + fn check_doc_hidden( |
| 816 | + &self, |
| 817 | + attr: &Attribute, |
| 818 | + meta_index: usize, |
| 819 | + meta: &NestedMetaItem, |
| 820 | + hir_id: HirId, |
| 821 | + target: Target, |
| 822 | + ) -> bool { |
| 823 | + if let Target::AssocConst |
| 824 | + | Target::AssocTy |
| 825 | + | Target::Method(MethodKind::Trait { body: true }) = target |
| 826 | + { |
| 827 | + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); |
| 828 | + let containing_item = self.tcx.hir().expect_item(parent_hir_id); |
| 829 | + |
| 830 | + if Target::from_item(containing_item) == Target::Impl { |
| 831 | + let meta_items = attr.meta_item_list().unwrap(); |
| 832 | + |
| 833 | + let (span, replacement_span) = if meta_items.len() == 1 { |
| 834 | + (attr.span, attr.span) |
| 835 | + } else { |
| 836 | + let meta_span = meta.span(); |
| 837 | + ( |
| 838 | + meta_span, |
| 839 | + meta_span.until(match meta_items.get(meta_index + 1) { |
| 840 | + Some(next_item) => next_item.span(), |
| 841 | + None => match attr.get_normal_item().args { |
| 842 | + MacArgs::Delimited(DelimSpan { close, .. }, ..) => close, |
| 843 | + _ => unreachable!(), |
| 844 | + }, |
| 845 | + }), |
| 846 | + ) |
| 847 | + }; |
| 848 | + |
| 849 | + // FIXME: #[doc(hidden)] was previously erroneously allowed on trait impl items, |
| 850 | + // so for backward compatibility only emit a warning and do not mark it as invalid. |
| 851 | + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| { |
| 852 | + lint.build("`#[doc(hidden)]` is ignored on trait impl items") |
| 853 | + .warn( |
| 854 | + "this was previously accepted by the compiler but is \ |
| 855 | + being phased out; it will become a hard error in \ |
| 856 | + a future release!", |
| 857 | + ) |
| 858 | + .note( |
| 859 | + "whether the impl item is `doc(hidden)` or not \ |
| 860 | + entirely depends on the corresponding trait item", |
| 861 | + ) |
| 862 | + .span_suggestion( |
| 863 | + replacement_span, |
| 864 | + "remove this attribute", |
| 865 | + String::new(), |
| 866 | + Applicability::MachineApplicable, |
| 867 | + ) |
| 868 | + .emit(); |
| 869 | + }); |
| 870 | + } |
| 871 | + } |
| 872 | + |
| 873 | + true |
| 874 | + } |
| 875 | + |
813 | 876 | /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
|
814 | 877 | fn check_attr_not_crate_level(
|
815 | 878 | &self,
|
@@ -928,7 +991,7 @@ impl CheckAttrVisitor<'_> {
|
928 | 991 | let mut is_valid = true;
|
929 | 992 |
|
930 | 993 | if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() {
|
931 |
| - for meta in list { |
| 994 | + for (meta_index, meta) in list.into_iter().enumerate() { |
932 | 995 | if let Some(i_meta) = meta.meta_item() {
|
933 | 996 | match i_meta.name_or_empty() {
|
934 | 997 | sym::alias
|
@@ -969,6 +1032,15 @@ impl CheckAttrVisitor<'_> {
|
969 | 1032 | is_valid = false;
|
970 | 1033 | }
|
971 | 1034 |
|
| 1035 | + sym::hidden if !self.check_doc_hidden(attr, |
| 1036 | + meta_index, |
| 1037 | + meta, |
| 1038 | + hir_id, |
| 1039 | + target, |
| 1040 | + ) => { |
| 1041 | + is_valid = false; |
| 1042 | + } |
| 1043 | + |
972 | 1044 | // no_default_passes: deprecated
|
973 | 1045 | // passes: deprecated
|
974 | 1046 | // plugins: removed, but rustdoc warns about it itself
|
|
0 commit comments