Skip to main content

document_module

Attribute Macro document_module 

Source
#[document_module]
Expand description

Orchestrates documentation generation for an entire module.

This macro provides a centralized way to handle documentation for Higher-Kinded Type (HKT) implementations. It performs a two-pass analysis of the module:

  1. Context Extraction: It scans for impl_kind! invocations and standard impl blocks to build a comprehensive mapping of associated types (a “projection map”).
  2. Documentation Generation: It processes all methods annotated with #[document_signature] or #[document_type_parameters], resolving Self and associated types using the collected context.
  3. Validation (Optional): Checks that impl blocks and methods have appropriate documentation attributes and emits compile-time warnings for missing documentation.

§Syntax

Due to inner macro attributes being unstable, use the following wrapper pattern:

#[fp_macros::document_module]
mod inner {
    // ... module content ...
}
pub use inner::*;

To disable validation warnings:

#[fp_macros::document_module(no_validation)]
mod inner {
    // ... module content ...
}
pub use inner::*;

§Generates

In-place replacement of #[document_signature] and #[document_type_parameters] attributes with generated documentation comments. It also resolves Self and Self::AssocType references to their concrete types based on the module’s projection map.

§Attributes

The macro supports several documentation-specific attributes for configuration:

  • #[document_default]: (Used inside impl or impl_kind!) Marks an associated type as the default to use when resolving bare Self references.
  • #[document_use = "AssocName"]: (Used on impl or fn) Explicitly specifies which associated type definition to use for resolution within that scope.

§Validation

By default, document_module validates that impl blocks and methods have appropriate documentation attributes and emits compile-time errors for missing documentation.

To disable validation, use #[document_module(no_validation)].

§Validation Rules

An impl block should have:

  • #[document_type_parameters] if it has type parameters
  • #[document_parameters] if it contains methods with receiver parameters (self, &self, &mut self)

A method should have:

  • #[document_signature] - always recommended for documenting the Hindley-Milner signature
  • #[document_type_parameters] if it has type parameters
  • #[document_parameters] if it has non-receiver parameters
§Examples of Validation
// This will emit warnings:
#[fp_macros::document_module]
mod inner {
    pub struct MyType;

    // WARNING: Impl block contains methods with receiver parameters
    // but no #[document_parameters] attribute
    impl MyType {
        // WARNING: Method should have #[document_signature] attribute
        pub fn process(&self, x: i32) -> i32 { x }
    }
}
// Properly documented (no warnings):
#[fp_macros::document_module]
mod inner {
    pub struct MyType;

    #[document_parameters("The MyType instance")]
    impl MyType {
        #[document_signature]
        #[document_parameters("The input value")]
        pub fn process(&self, x: i32) -> i32 { x }
    }
}
// Disable validation to suppress warnings:
#[fp_macros::document_module(no_validation)]
mod inner {
    // ... undocumented code won't produce warnings ...
}

§Hierarchical Configuration

When resolving the concrete type of Self, the macro follows this precedence:

  1. Method Override: #[document_use = "AssocName"] on the method.
  2. Impl Block Override: #[document_use = "AssocName"] on the impl block.
  3. (Type, Trait)-Scoped Default: #[document_default] on the associated type definition in a trait impl block.
  4. Module Default: #[document_default] on the associated type definition in impl_kind!.

§Examples

// Invocation
#[fp_macros::document_module]
mod inner {
    use super::*;

    impl_kind! {
        for MyBrand {
            #[document_default]
            type Of<'a, T: 'a>: 'a = MyType<T>;
        }
    }

    impl Functor for MyBrand {
        #[document_signature]
        fn map<'a, A: 'a, B: 'a, Func>(
            f: Func,
            fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
        ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
        where
            Func: Fn(A) -> B + 'a
        {
            todo!()
        }
    }
}
pub use inner::*;

// Expanded code
mod inner {
    use super::*;

    // ... generated Kind implementations ...

    impl Functor for MyBrand {
        /// `forall a b. (a -> b, MyType a) -> MyType b`
        fn map<'a, A: 'a, B: 'a, Func>(
            f: Func,
            fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
        ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
        where
            Func: Fn(A) -> B + 'a
        {
            todo!()
        }
    }
}
pub use inner::*;