Change:
I tried to create a minimum example from an issue we've seen in our project (). I tried running: On the following crate: : I expected to see this happen: The command should succeed. Instead, this happened: It crashed with an ICE <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
This issue may be related to , however I can only reproduce it on the nightly build. On the stable channel, rustdoc succeeds.
cc
does this reproduce on beta?
I know I'm not celinval, but I've been able to reduce this to a test case, and yeah, it reproduces on beta.
That was quick. Thank you!
Reopening to track beta breakage.
I was silly and nominated even though the PR has already been nominated, and that's really the thing that's supposed to be. Please ignore, and sorry for the noise.

Discussion:
.map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)), ); items.extend(self.mods.iter().map(|x| x.clean(cx))); <del> items.extend( self.items .iter() .flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)), ); </del> <ins> // Split up imports from all other items. // // This covers the case where somebody does an import which should pull in an item, // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. let mut inserted = FxHashSet::default(); items.extend(self.items.iter().flat_map(|(item, renamed)| { // First, lower everything other than imports. if matches!(item.kind, hir::ItemKind::Use(..)) { return Vec::new(); } let v = clean_maybe_renamed_item(cx, item, *renamed); for item in &v { if let Some(name) = item.name { inserted.insert((item.type_(), name)); } } v })); items.extend(self.items.iter().flat_map(|(item, renamed)| { // Now we actually lower the imports, skipping everything else. if !matches!(item.kind, hir::ItemKind::Use(..)) { return Vec::new(); } let mut v = clean_maybe_renamed_item(cx, item, *renamed); v.drain_filter(|item| { if let Some(name) = item.name { // If an item with the same type and name already exists, // it takes priority over the inlined stuff. !inserted.insert((item.type_(), name)) } else { false } }); v })); </ins> // determine if we should display the inner contents or // the outer `mod` item for the source code.

<ins> pub struct Option; impl Option { pub fn unwrap(self) {} } mod macros { use crate::Option; /// [`Option::unwrap`] #[macro_export] macro_rules! print { () => () } } mod structs { use crate::Option; /// [`Option::unwrap`] pub struct Print; } pub use structs::Print; </ins>

<ins> // aux-build:issue-99221-aux.rs // build-aux-docs // ignore-cross-compile #![crate_name = "foo"] #[macro_use] extern crate issue_99221_aux; pub use issue_99221_aux::*; // @count foo/index.html '//a[@class="macro"]' 1 mod inner { #[macro_export] macro_rules! print { () => () } } </ins>

<ins> // aux-build:issue-99221-aux.rs // build-aux-docs // ignore-cross-compile #![crate_name = "foo"] #[macro_use] extern crate issue_99221_aux; pub use issue_99221_aux::*; // @count foo/index.html '//a[@class="macro"]' 1 #[macro_export] macro_rules! print { () => () } </ins>

<ins> // aux-build:issue-99221-aux.rs // build-aux-docs // ignore-cross-compile #![crate_name = "foo"] #[macro_use] extern crate issue_99221_aux; pub use issue_99221_aux::*; // @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1 pub struct Print; </ins>