"error: expected item after attributes" occurs when running doctests on the nightly

//! ```
//! # #[cfg(feature = "std")]
//! # {
//! use std::{process::ExitCode, str};
//!
//! fn main() -> ExitCode {
//!     let bytes = b"Hello, world!";
//!     if str::from_utf8(bytes).is_ok() {
//!         ExitCode::SUCCESS
//!     } else {
//!         ExitCode::FAILURE
//!     }
//! }
//! # }
//!
//! #[cfg(not(feature = "std"))]
//! fn main() {}
//! ```

...

When I ran the above on the nightly, the error in the title occurred. This compiled fine on the latest stable. When I wrote code similar to this as normal code, a compilation error occurred even on the latest stable.

Is this compilation error occurring because the above doctests is incorrect, or is this occurring because of a bug on the nightly?

I don't know why it would compile on stable, but the code is not valid rust.

you cannot have top level blocks. in regular code, you can use the cfg-if crate, but I don't think it could be used in doctests.

as a workaround, you can put the conditional code in a mod or fn, and call it based on the cfg features, example:

#[cfg(not(feature = "std"))]
pub fn test_main() {
	println!("hello, no std world!");
}


#[cfg(feature = "std")]
pub fn test_main() {
	println!("hello, std world");
}


fn main() {
    test_main();
}

EDIT:

the above wording may be confusing. what I meant to say is, you can only put #[cfg()] on items, rust have items like mod or fn, but a block at top level is not a valid item. doctest code is typically not very long, you can just put them in a single function, like fn main(), but if you want to organize the snippet as mulpitle functions, but you don't want to add #[cfg()] for all of them, you can put them in a mod, which can be gated with cfg features. a better example would use a mod like this;

#[cfg(not(feature = "std"))]
pub fn main() {
	println!("hello, no std world!");
}

#[cfg(feature = "std")]
fn main() {
	__with_std::main()
}

#[cfg(feature = "std")]
mod __with_std {
	use xyz::abc;
	fn foo() {}
	fn bar() {}
	pub fn main() {
		foo();
		bar();
	}
}
2 Likes