rustdoc: move manual "extern crate" statements outside automatic "fn main"s in doctests by QuietMisdreavus · Pull Request #48106 · rust-lang/rust (original) (raw)

Gated on #48095 - I based the branch atop that so i could show off the change in one of its tests, the actual change in this PR is just the last commit

There are a handful of unfortunate assumptions in the way rustdoc processes extern crate statements in doctests:

  1. In the absence of an extern crate statement in the test, if the test also uses the local crate name, it will automatically insert an extern crate cratename; statement into the test.
  2. If the doctest does include an extern crate statement, rustdoc will not automatically insert one, on the assumption that doing so would introduce a duplicate import.
  3. If a doctest does not have the substring fn main outside a comment, rustdoc will wrap the whole doctest in a generated fn main so it can be compiled.

In short, whenever you write a doctest like this...

//! extern crate my_crate; //! my_crate::some_cool_thing();

...rustdoc will turn it into (something like) this:

fn main() { extern crate my_crate; my_crate::some_cool_thing(); }

This creates issues when compiled, because now my_crate isn't even properly in scope! This forces people who want to have multiple crates in their doctests (or an explicit extern crate statement) to also manually include their own fn main, so rustdoc doesn't put their imports in the wrong place.

This PR just taps into another processing step rustdoc does to doctests: Whenever you add an #![inner_attribute] to the beginning of a doctest, rustdoc will actually splice those out and put it before the generated fn main. Now, we can just do the same with extern crates at the beginning, too, and get a much nicer experience.

Now, the above example will be converted into this:

extern crate my_crate; fn main() { my_crate::some_cool_thing(); }