Change:
I expected this change to work: But it causes to panic: <details<summaryBacktrace</summary</detailsI don't have time to look into it right now, but I wouldn't expect it to be too hard to fix and it would reduce the memory usage of rustdoc by quite a lot. I'd suggest starting by adding a bunch of assertions that the old and new behavior of is the same and investigating the assertion failures. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
Since would unconditionally add a final newline, shouldn't the note say that (instead of "this can") and the 'pop's be unconditional? Across the entire codebase, there's just one other invocation of 'adddocfragment' (currently line 1087 ); it seems that that doesn't need a newline popped. Instead, I think the last function you modified () should only have a newline popped for the last , as would only be false for the last , as far as I can tell. I made a commit to that effect in the PR above, though I have to resolve the merge conflict somehow.
feel free to try that out and see if it works :) like I said, I don't have time to work on it right now.

Discussion:
crate parent_module: Option<DefId>, crate doc: Symbol, crate kind: DocFragmentKind, <del> crate need_backline: bool, </del> crate indent: usize, }

RawDoc, } <del> // The goal of this function is to apply the `DocFragment` transformations that are required when // transforming into the final markdown. So the transformations in here are: // // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain //   multiple lines in case of `#[doc = ""]`). // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the //   `need_backline` field). </del> <ins> /// The goal of this function is to apply the `DocFragment` transformation that is required when /// transforming into the final Markdown, which is applying the computed indent to each line in /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`). /// /// Note: remove the trailing newline where appropriate </ins> fn add_doc_fragment(out: &mut String, frag: &DocFragment) { let s = frag.doc.as_str(); <del> let mut iter = s.lines().peekable(); </del> <ins> let mut iter = s.lines(); if s == "" { out.push('n'); return; } </ins> while let Some(line) = iter.next() { if line.chars().any(|c| !c.is_whitespace()) { assert!(line.len() >= frag.indent);

} else { out.push_str(line); } <del> if iter.peek().is_some() { out.push('n'); } } if frag.need_backline { </del> out.push('n'); } }

for frag in doc_strings { add_doc_fragment(&mut acc, frag); } <ins> acc.pop(); </ins> acc }

additional_attrs: Option<(&[ast::Attribute], DefId)>, ) -> Attributes { let mut doc_strings: Vec<DocFragment> = vec![]; let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| { if let Some(value) = attr.doc_str() { trace!("got doc_str={:?}", value);

DocFragmentKind::RawDoc }; <del> let frag = DocFragment { span: attr.span, doc: value, kind, parent_module, need_backline: false, indent: 0, }; if let Some(prev) = doc_strings.last_mut() { prev.need_backline = true; } </del> <ins> let frag = DocFragment { span: attr.span, doc: value, kind, parent_module, indent: 0 }; </ins> doc_strings.push(frag);

} add_doc_fragment(&mut out, new_frag); } <ins> out.pop(); </ins> if out.is_empty() { None } else { Some(out) } }

/// The module can be different if this is a re-export with added documentation. crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> { let mut ret = FxHashMap::default(); <ins> if self.doc_strings.len() == 0 { return ret; } let last_index = self.doc_strings.len() - 1; </ins> <del> for new_frag in self.doc_strings.iter() { </del> <ins> for (i, new_frag) in self.doc_strings.iter().enumerate() { </ins> let out = ret.entry(new_frag.parent_module).or_default(); add_doc_fragment(out, new_frag); <ins> if i == last_index { out.pop(); } </ins> } ret }

parent_module: None, doc: Symbol::intern(s), kind: DocFragmentKind::SugaredDoc, <del> need_backline: false, </del> indent: 0, }] }