Is it a misuse or a bug with feature `doc_cfg`?

minimal example: the crate has a feature gate public-all, foo.rs is an empty file.
and lib.rs contains the following code:

#![feature(doc_cfg)]
/// foo is visible in either doc or public-all feature gate
#[doc(cfg(any(doc, feature="public-all")))]
pub mod foo;
#[cfg(not(any(doc, feature="public-all")))]
mod foo;

such code compiles with cargo doc (since doc is provided, pub mod foo compiles, mod foo vanished).

With cargo build, I suppose #[doc(cfg(any(doc, feature="public-all")))] makes pub mod foo vanishes, but an error generates:

error[E0428]: the name `foo` is defined multiple times
 --> src/lib.rs:6:1
  |
4 | pub mod foo;
  | ------------ previous definition of the module `foo` here
5 | #[cfg(not(any(doc, feature="public-all")))]
6 | mod foo;
  | ^^^^^^^^ `foo` redefined here
  |
  = note: `foo` must be defined only once in the type namespace of this module

For more information about this error, try `rustc --explain E0428`.
error: could not compile `min` (lib) due to 1 previous error

I have no idea why #[doc(cfg(any(doc, feature="public-all")))] keeps pub mod foo compiles

doc is false, feature does not contains public-all, which yields a negative result for any(doc, feature="public-all"), and thus doc(cfg(false)) should yield a not-compile signal, and the error should not occurs.

What's wrong?


If you have a shell, you could use these code to see the error directly:

(Before you paste, a better choice is to check whether the script contains invisible characters (here of coursely contains none) Be aware of invisible characters, it is said that, they may do anything)

cargo new --lib min && cd "$_"
echo -e "[features]\npublic-all = []" >> Cargo.toml
touch src/foo.rs 
cat > src/lib.rs << EOF
#![feature(doc_cfg)]
/// foo is visible in either doc or public-all feature gate
#[doc(cfg(any(doc, feature="public-all")))]
pub mod foo;
#[cfg(not(any(doc, feature="public-all")))]
mod foo;
EOF
cargo build

Solved in a dirty way.

I suppose #[doc(cfg(any(doc, feature="public-all")))] is a normal cfg attribute, but it seems not so.
it still needs to add a cfg attribute.

I just wonder whether it is a bug, or it is designed to do so.

These code works fine, but really dirty.

I'm trying to write a decl_macro for that, there may exists some hygiene issues, or just I misuse the doc attr.

I might put another bug later If I really found that is a ugly bug.

#![feature(doc_cfg)]
/// foo is visible in either doc or public-all feature gate
#[cfg(any(doc,feature="public-all"))] // enough
#[doc(cfg(feature="public-all"))] // no need to put `doc` into the cfg features
pub mod foo;
#[cfg(not(any(doc, feature="public-all")))]
mod foo;

Yes doc(cfg) is just a decoration for documentation. You'd probably be interested in the separate gate feature(doc_auto_cfg) which infers the cfg gate to show in documentation for many common cases. doc(cfg) then becomes just for cases where the documented cfg differs from the actual cfg used to gate the documented version of the item, for which purpose it'd be bad if doc(cfg) also did actual gating.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.