From a6cfabc88a79fe039a9c3d0c541f6517fb9767e2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 19:42:52 +0200 Subject: [PATCH 1/3] Avoid ICE in rustdoc. --- src/librustdoc/clean/auto_trait.rs | 12 +++++++----- src/test/rustdoc/fn-bound.rs | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/fn-bound.rs diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 71f070f2678b3..6697952293e56 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -354,9 +354,7 @@ where ty_to_bounds .into_iter() .flat_map(|(ty, mut bounds)| { - if let Some(data) = ty_to_fn.get(&ty) { - let (poly_trait, output) = - (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new)); + if let Some((Some(ref poly_trait), ref output)) = ty_to_fn.get(&ty) { let mut new_path = poly_trait.trait_.clone(); let last_segment = new_path.segments.pop().expect("segments were empty"); @@ -374,8 +372,9 @@ where GenericArgs::Parenthesized { inputs, output } => (inputs, output), }; + let output = output.as_ref().cloned().map(Box::new); if old_output.is_some() && old_output != output { - panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1); + panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, output); } let new_params = GenericArgs::Parenthesized { inputs: old_input, output }; @@ -385,7 +384,10 @@ where .push(PathSegment { name: last_segment.name, args: new_params }); bounds.insert(GenericBound::TraitBound( - PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params }, + PolyTrait { + trait_: new_path, + generic_params: poly_trait.generic_params.clone(), + }, hir::TraitBoundModifier::None, )); } diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs new file mode 100644 index 0000000000000..7b44ee7b4b5bf --- /dev/null +++ b/src/test/rustdoc/fn-bound.rs @@ -0,0 +1,17 @@ +use std::iter::Peekable; + +pub struct Span { + inner: Peekable>, +} + +struct ConditionalIterator { + f: F, +} + +impl Iterator for ConditionalIterator { + type Item = (); + + fn next(&mut self) -> Option { + todo!() + } +} From eab3b05b622890228e001feff5f5751196cc12ed Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Aug 2022 21:09:09 +0200 Subject: [PATCH 2/3] Synthetize a trait ref when none is available. --- src/librustdoc/clean/auto_trait.rs | 18 ++++++++++++------ src/test/rustdoc/fn-bound.rs | 4 +++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 6697952293e56..af33c1a6ada74 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -348,13 +348,13 @@ where fn make_final_bounds( &self, ty_to_bounds: FxHashMap>, - ty_to_fn: FxHashMap, Option)>, + ty_to_fn: FxHashMap)>, lifetime_to_bounds: FxHashMap>, ) -> Vec { ty_to_bounds .into_iter() .flat_map(|(ty, mut bounds)| { - if let Some((Some(ref poly_trait), ref output)) = ty_to_fn.get(&ty) { + if let Some((ref poly_trait, ref output)) = ty_to_fn.get(&ty) { let mut new_path = poly_trait.trait_.clone(); let last_segment = new_path.segments.pop().expect("segments were empty"); @@ -473,7 +473,7 @@ where let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut ty_to_traits: FxHashMap> = Default::default(); - let mut ty_to_fn: FxHashMap, Option)> = Default::default(); + let mut ty_to_fn: FxHashMap)> = Default::default(); for p in clean_where_predicates { let (orig_p, p) = (p, p.clean(self.cx)); @@ -537,8 +537,8 @@ where if is_fn { ty_to_fn .entry(ty.clone()) - .and_modify(|e| *e = (Some(poly_trait.clone()), e.1.clone())) - .or_insert(((Some(poly_trait.clone())), None)); + .and_modify(|e| *e = (poly_trait.clone(), e.1.clone())) + .or_insert(((poly_trait.clone()), None)); ty_to_bounds.entry(ty.clone()).or_default(); } else { @@ -561,7 +561,13 @@ where .and_modify(|e| { *e = (e.0.clone(), Some(rhs.ty().unwrap().clone())) }) - .or_insert((None, Some(rhs.ty().unwrap().clone()))); + .or_insert(( + PolyTrait { + trait_: trait_.clone(), + generic_params: Vec::new(), + }, + Some(rhs.ty().unwrap().clone()), + )); continue; } diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs index 7b44ee7b4b5bf..d5d5838d37580 100644 --- a/src/test/rustdoc/fn-bound.rs +++ b/src/test/rustdoc/fn-bound.rs @@ -4,10 +4,12 @@ pub struct Span { inner: Peekable>, } -struct ConditionalIterator { +pub struct ConditionalIterator { f: F, } + +// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header in-band"]' 'impl Iterator for ConditionalIterator' impl Iterator for ConditionalIterator { type Item = (); From 28e4b9e64e436f52b03ba53e0f859a206ef3c93e Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Mon, 8 Aug 2022 14:09:55 -0700 Subject: [PATCH 3/3] Add regression test comment --- src/test/rustdoc/fn-bound.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs index d5d5838d37580..4c4ffddc8a648 100644 --- a/src/test/rustdoc/fn-bound.rs +++ b/src/test/rustdoc/fn-bound.rs @@ -1,3 +1,5 @@ +// Regression test for #100143 + use std::iter::Peekable; pub struct Span {