about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-27 17:14:46 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-09-27 11:29:49 +0200
commit1561efe41afe40c1afaf3d11316ef754d9a8f9a9 (patch)
tree7e5eaf0c31a47b678cc1554244e41bab30ef93e6
parentc06a076634e4feab47e133fe6325af9659bab082 (diff)
downloadrust-1561efe41afe40c1afaf3d11316ef754d9a8f9a9.tar.gz
rust-1561efe41afe40c1afaf3d11316ef754d9a8f9a9.zip
Add code documentation, improve code and improve error message
-rw-r--r--compiler/rustc_passes/messages.ftl2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs9
-rw-r--r--src/librustdoc/clean/types.rs13
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs14
-rw-r--r--tests/rustdoc-ui/lints/doc_cfg_hide.stderr4
5 files changed, 28 insertions, 14 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 8326ddaf194..a9a0f6d8b51 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -147,7 +147,7 @@ passes_doc_auto_cfg_expects_hide_or_show =
     `only "hide" or "show" are allowed in "#[doc(auto_cfg(...))]"`
 
 passes_doc_auto_cfg_hide_show_expects_list =
-    `#![doc(auto_cfg({$attr_name}(...)))]` only expects a list of items
+    `#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items
 
 passes_doc_auto_cfg_hide_show_unexpected_item =
     `#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/values items
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 38b67e2f9dc..c521467b556 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
 use std::slice;
 
 use rustc_abi::{Align, ExternAbi, Size};
-use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast};
+use rustc_ast::{AttrStyle, LitKind, MetaItem, MetaItemInner, MetaItemKind, ast};
 use rustc_attr_parsing::{AttributeParser, Late};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
@@ -1161,10 +1161,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Check that the `#![doc(auto_cfg(..))]` attribute has expected input.
-    fn check_doc_auto_cfg(&self, meta: &MetaItemInner, hir_id: HirId) {
-        let MetaItemInner::MetaItem(meta) = meta else {
-            unreachable!();
-        };
+    fn check_doc_auto_cfg(&self, meta: &MetaItem, hir_id: HirId) {
         match &meta.kind {
             MetaItemKind::Word => {}
             MetaItemKind::NameValue(lit) => {
@@ -1286,7 +1283,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         }
 
                         Some(sym::auto_cfg) => {
-                            self.check_doc_auto_cfg(meta, hir_id);
+                            self.check_doc_auto_cfg(i_meta, hir_id);
                         }
 
                         Some(sym::inline | sym::no_inline) => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2ec97a57087..545f1ef6da4 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -922,11 +922,19 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
         .flatten()
 }
 
+/// This type keeps track of (doc) cfg information as we go down the item tree.
 #[derive(Clone, Debug)]
 pub(crate) struct CfgInfo {
+    /// List of `doc(auto_cfg(hide(...)))` cfgs.
     hidden_cfg: FxHashSet<Cfg>,
+    /// Current computed `cfg`. Each time we enter a new item, this field is updated as well while
+    /// taking into account the `hidden_cfg` information.
     current_cfg: Cfg,
+    /// Whether the `doc(auto_cfg())` feature is enabled or not at this point.
     auto_cfg_active: bool,
+    /// If the parent item used `doc(cfg(...))`, then we don't want to overwrite `current_cfg`,
+    /// instead we will concatenate with it. However, if it's not the case, we need to overwrite
+    /// `current_cfg`.
     parent_is_doc_cfg: bool,
 }
 
@@ -962,6 +970,11 @@ fn show_hide_show_conflict_error(
     diag.emit();
 }
 
+/// This function checks if a same `cfg` is present in both `auto_cfg(hide(...))` and
+/// `auto_cfg(show(...))` on the same item. If so, it emits an error.
+///
+/// Because we go through a list of `cfg`s, we keep track of the `cfg`s we saw in `new_show_attrs`
+/// and in `new_hide_attrs` arguments.
 fn handle_auto_cfg_hide_show(
     tcx: TyCtxt<'_>,
     cfg_info: &mut CfgInfo,
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 802f2fbe569..ea77065ac07 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -30,7 +30,8 @@ struct CfgPropagator<'a, 'tcx> {
     cfg_info: CfgInfo,
 }
 
-fn should_retain(token: &TokenTree) -> bool {
+/// Returns true if the provided `token` is a `cfg` ident.
+fn is_cfg_token(token: &TokenTree) -> bool {
     // We only keep `doc(cfg)` items.
     matches!(
         token,
@@ -47,7 +48,9 @@ fn should_retain(token: &TokenTree) -> bool {
     )
 }
 
-fn filter_tokens_from_list(args_tokens: &TokenStream) -> Vec<TokenTree> {
+/// We only want to keep `#[cfg()]` and `#[doc(cfg())]` attributes so we rebuild a vec of
+/// `TokenTree` with only the tokens we're interested into.
+fn filter_non_cfg_tokens_from_list(args_tokens: &TokenStream) -> Vec<TokenTree> {
     let mut tokens = Vec::with_capacity(args_tokens.len());
     let mut skip_next_delimited = false;
     for token in args_tokens.iter() {
@@ -58,7 +61,7 @@ fn filter_tokens_from_list(args_tokens: &TokenStream) -> Vec<TokenTree> {
                 }
                 skip_next_delimited = false;
             }
-            token if should_retain(token) => {
+            token if is_cfg_token(token) => {
                 skip_next_delimited = false;
                 tokens.push(token.clone());
             }
@@ -70,7 +73,8 @@ fn filter_tokens_from_list(args_tokens: &TokenStream) -> Vec<TokenTree> {
     tokens
 }
 
-// We only care about `#[cfg()]` and `#[doc(cfg())]`, we discard everything else.
+/// This function goes through the attributes list (`new_attrs`) and extract the `cfg` tokens from
+/// it and put them into `attrs`.
 fn add_only_cfg_attributes(attrs: &mut Vec<Attribute>, new_attrs: &[Attribute]) {
     for attr in new_attrs {
         if attr.is_doc_comment() {
@@ -84,7 +88,7 @@ fn add_only_cfg_attributes(attrs: &mut Vec<Attribute>, new_attrs: &[Attribute])
             if ident == sym::doc
                 && let AttrArgs::Delimited(args) = &mut normal.args
             {
-                let tokens = filter_tokens_from_list(&args.tokens);
+                let tokens = filter_non_cfg_tokens_from_list(&args.tokens);
                 args.tokens = TokenStream::new(tokens);
                 attrs.push(attr);
             } else if ident == sym::cfg_trace {
diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
index 0e9db5a30d8..9e820a77b5e 100644
--- a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
+++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
@@ -1,4 +1,4 @@
-error: `#![doc(auto_cfg(hide(...)))]` only expects a list of items
+error: `#![doc(auto_cfg(hide(...)))]` expects a list of items
   --> $DIR/doc_cfg_hide.rs:2:8
    |
 LL | #![doc(auto_cfg(hide = "test"))]
@@ -6,7 +6,7 @@ LL | #![doc(auto_cfg(hide = "test"))]
    |
    = note: `#[deny(invalid_doc_attributes)]` on by default
 
-error: `#![doc(auto_cfg(hide(...)))]` only expects a list of items
+error: `#![doc(auto_cfg(hide(...)))]` expects a list of items
   --> $DIR/doc_cfg_hide.rs:3:8
    |
 LL | #![doc(auto_cfg(hide))]