diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 60592cc186ed8..914365b003e18 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -448,8 +448,7 @@ fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static { /// /// The inverse of this filtering logic can be found in the `Clean` /// implementation for `AssociatedType` -fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) - -> clean::Generics { +fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { for pred in &mut g.where_predicates { match *pred { clean::WherePredicate::BoundPredicate { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5499351e9514b..8d02fd2686603 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1190,16 +1190,36 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { pub struct Generics { pub lifetimes: Vec, pub type_params: Vec, - pub where_predicates: Vec + pub where_predicates: Vec, } impl Clean for hir::Generics { fn clean(&self, cx: &DocContext) -> Generics { - Generics { + let mut g = Generics { lifetimes: self.lifetimes.clean(cx), type_params: self.ty_params.clean(cx), where_predicates: self.where_clause.predicates.clean(cx) + }; + + // Some duplicates are generated for ?Sized bounds between type params and where + // predicates. The point in here is to move the bounds definitions from type params + // to where predicates when such cases occur. + for where_pred in &mut g.where_predicates { + match *where_pred { + WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => { + if bounds.is_empty() { + for type_params in &mut g.type_params { + if &type_params.name == name { + mem::swap(bounds, &mut type_params.bounds); + break + } + } + } + } + _ => continue, + } } + g } } @@ -1225,7 +1245,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let mut where_predicates = preds.predicates.to_vec().clean(cx); // Type parameters and have a Sized bound by default unless removed with - // ?Sized. Scan through the predicates and mark any type parameter with + // ?Sized. Scan through the predicates and mark any type parameter with // a Sized bound, removing the bounds as we find them. // // Note that associated types also have a sized bound by default, but we diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index dd36b28bb39ac..63ebb16e5e009 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -38,6 +38,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { let mut lifetimes = Vec::new(); let mut equalities = Vec::new(); let mut tybounds = Vec::new(); + for clause in clauses { match clause { WP::BoundPredicate { ty, bounds } => { diff --git a/src/test/rustdoc/where-sized.rs b/src/test/rustdoc/where-sized.rs new file mode 100644 index 0000000000000..c175c839c0f21 --- /dev/null +++ b/src/test/rustdoc/where-sized.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// @has - '//*[@class="rust fn"]' 'pub fn foo(_: &X)' +// @has - '//*[@class="rust fn"]' 'where X: ?Sized,' +pub fn foo(_: &X) where X: ?Sized {}