Skip to content

rustfmt does not understand cfg_attr used to start a rustdoc example/test #5420

Closed as not planned

Description

With wrap_comments = true, rustfmt mangles source code (in different ways) within a test/example in rustdoc if #![cfg_attr] is used to enable the start of a code block:

Sample input:

#![cfg_attr(not(feature = "std"), doc = "```ignore")]
#![cfg_attr(feature = "std", doc = "```")]
//! use size::Size;
//!
//! // This is a short comment. It causes no problems.
//! let s1 = Size::from_mib(13) / 2;
//! assert_eq!(s1, Size::from_mib(6.5_f32));
//!
//! // This is a contrived long comment line within what should be detected as a rustdoc section. With `wrap_comments = true`, this comment is mangled.
//! let s3 = Size::from_mib(12) - Size::from_mib(14.2_f64);
//! assert_eq!(s3, Size::from_kib(-2252.8));
//! ```
//!
//! I think `rustfmt` treats everything here as code and doesn't touch it via either of `wrap_comments` or `max_width`, although one or the other should?
//! My guess is that the closing ``` above are treated as opening ``` because the original ``` via
//! the cfg_attr macro isn't recognized.

The result after a format run:

#![cfg_attr(not(feature = "std"), doc = "```ignore")]
#![cfg_attr(feature = "std", doc = "```")]
//! use size::Size;
//!
//! // This is a short comment. It causes no problems.
//! let s1 = Size::from_mib(13) / 2;
//! assert_eq!(s1, Size::from_mib(6.5_f32));
//!
//! // This is a contrived long comment line within what should be detected as a
//! rustdoc section. With `wrap_comments = true`, this comment is mangled.
//! let s3 = Size::from_mib(12) - Size::from_mib(14.2_f64);
//! assert_eq!(s3, Size::from_kib(-2252.8));
//! ```
//! 
//! I think `rustfmt` treats everything here as code and doesn't touch it via either of `wrap_comments` or `max_width`, although one or the other should?
//! My guess is that the closing ``` above are treated as opening ``` because the original ``` via
//! the cfg_attr macro isn't recognized.

As you can see,

  • regardless of whether it's being run with or without the std feature, the section should be recognized as code, just that it will either be ignored or executed by the test harness
  • the comment in the code within the rustdoc has been wrapped to the next line, but not continued with // so it will be treated as code (and fail).
  • the text after the closing ``` seems to be treated like code, but it's not reformatted via either of wrap_comments or max_width despite being in violation of both. As I mention, I think it's because the closing ``` is treated as opening one instead (because the actual opening one is not seen)

But I'm not sure that's actually the explanation because with a different input, rustfmt mangles the closing ``` as well (for some reason it doesn't happen with the example above):

input:

//! This is a rustdoc comment that goes past the default allowed width of eighty characters. rustfmt will re-wrap this comment when run with `wrap_comments`
//! enabled.
//!
//! The preceding line does not have any whitespace and is a total of three backslashes followed by a new line (`\n`). This does not change after a
//! `rustfmt` run.
//!
//! Some examples of supported mathematical operations:
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
#![cfg_attr(feature = "std", doc = "```")]
//! use size::Size;
//!
//! // No trailing whitespace is introduced on the line above
//! let s1 = Size::from_mib(13) / 2;
//! assert_eq!(s1, Size::from_mib(6.5_f32));
//!
//! // Nor is any trailing whitespace introduced on the line above or the line below, even though this comment exceeds the maximum supported width
//! let s3 = Size::from_mib(12) - Size::from_mib(14.2_f64);
//! assert_eq!(s3, Size::from_kib(-2252.8));
//! ```
//!
//! In this section of the module documentation, `rustfmt` will introduce a trailing whitespace on the line above after
//! it is executed with `wrap_comments = true`.
//!
//! `rustfmt` does not introduce trailing whitespace on the line above this comment, even though it too is rewrapped from its long length.

formatted output:

//! This is a rustdoc comment that goes past the default allowed width of eighty
//! characters. rustfmt will re-wrap this comment when run with `wrap_comments`
//! enabled.
//!
//! The preceding line does not have any whitespace and is a total of three
//! backslashes followed by a new line (`\n`). This does not change after a
//! `rustfmt` run.
//!
//! Some examples of supported mathematical operations:
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
#![cfg_attr(feature = "std", doc = "```")]
//! use size::Size;
//!
//! // No trailing whitespace is introduced on the line above
//! let s1 = Size::from_mib(13) / 2;
//! assert_eq!(s1, Size::from_mib(6.5_f32));
//!
//! // Nor is any trailing whitespace introduced on the line above or the line
//! below, even though this comment exceeds the maximum supported width let s3 =
//! Size::from_mib(12) - Size::from_mib(14.2_f64); assert_eq!(s3,
//! Size::from_kib(-2252.8)); ```
//! 
//! In this section of the module documentation, `rustfmt` will introduce a trailing whitespace on the line above after
//! it is executed with `wrap_comments = true`.
//!
//! `rustfmt` does not introduce trailing whitespace on the line above this comment, even though it too is rewrapped from its long length.

Notice how here the text after the closing ``` is still not reformatted but the closing ``` was treated as text and merged with the (incorrectly) wrapped contents of the previous line. So it might be more complicated than that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions