From 7eefe2b4735b018efa50fa1e5ebfaf4db868ba22 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 14 May 2018 12:07:34 +0900 Subject: [PATCH] Fix rustdoc panic with `impl Trait` in type parameters --- src/librustdoc/clean/mod.rs | 35 ++++++++++++++++++++---- src/test/rustdoc/universal-impl-trait.rs | 14 +++++++++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a1d77f4145b83..c233e57a8018e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1754,16 +1754,39 @@ pub struct Generics { impl Clean for hir::Generics { fn clean(&self, cx: &DocContext) -> Generics { + // Synthetic type-parameters are inserted after normal ones. + // In order for normal parameters to be able to refer to synthetic ones, + // scans them first. + fn is_impl_trait(param: &hir::GenericParam) -> bool { + if let hir::GenericParam::Type(ref tp) = param { + tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) + } else { + false + } + } + let impl_trait_params = self.params + .iter() + .filter(|p| is_impl_trait(p)) + .map(|p| { + let p = p.clean(cx); + if let GenericParamDef::Type(ref tp) = p { + cx.impl_trait_bounds + .borrow_mut() + .insert(tp.did, tp.bounds.clone()); + } else { + unreachable!() + } + p + }) + .collect::>(); + let mut params = Vec::with_capacity(self.params.len()); - for p in &self.params { + for p in self.params.iter().filter(|p| !is_impl_trait(p)) { let p = p.clean(cx); - if let GenericParamDef::Type(ref tp) = p { - if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { - cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone()); - } - } params.push(p); } + params.extend(impl_trait_params); + let mut g = Generics { params, where_predicates: self.where_clause.predicates.clean(cx) diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs index af51ff3d9419e..1c1124282d478 100644 --- a/src/test/rustdoc/universal-impl-trait.rs +++ b/src/test/rustdoc/universal-impl-trait.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(universal_impl_trait)] #![crate_name = "foo"] use std::io::Read; +use std::borrow::Borrow; // @has foo/fn.foo.html // @has - //pre 'foo(' @@ -51,3 +51,15 @@ impl S { // @has - 'method(' // @matches - '_x: impl Trait for S {} + +// @has foo/fn.much_universe.html +// @matches - 'T:.+Borrow.+impl .+trait\.Trait\.html' +// @matches - 'U:.+IntoIterator.+= impl.+Iterator\.html.+= impl.+Clone\.html' +// @matches - '_: impl .+trait\.Read\.html.+ \+ .+trait\.Clone\.html' +pub fn much_universe< + T: Borrow, + U: IntoIterator>, +>( + _: impl Read + Clone, +) { +}