diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6dd07695b33f1998ca5907b2323b2ea3ed385833..6c243a5d795ec9a58077d7f50684faaa001cddfd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -958,7 +958,7 @@ fn clean(&self, cx: &DocContext) -> Generics { Generics { type_params: simplify::ty_params(stripped_typarams), lifetimes: stripped_lifetimes, - where_predicates: simplify::where_clauses(where_predicates), + where_predicates: simplify::where_clauses(cx, where_predicates), } } } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 367551fa1491c3e88978ab9c070e664f7264a12a..03f056a69232ed5d30a6ea8c77e6a87e95150deb 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -29,11 +29,16 @@ use std::mem; use std::collections::HashMap; -use clean; -use clean::WherePredicate as WP; +use rustc::middle::subst; +use rustc::middle::ty; +use syntax::ast; + use clean::PathParameters as PP; +use clean::WherePredicate as WP; +use clean::{self, Clean}; +use core::DocContext; -pub fn where_clauses(clauses: Vec) -> Vec { +pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { // First, partition the where clause into its separate components let mut params = HashMap::new(); let mut lifetimes = Vec::new(); @@ -90,16 +95,25 @@ pub fn where_clauses(clauses: Vec) -> Vec { clean::ResolvedPath { did, ref mut path, ..} => (did, path), _ => return false, }; - if did != trait_did { return false } + // If this QPath's trait `trait_did` is the same as, or a supertrait + // of, the bound's trait `did` then we can keep going, otherwise + // this is just a plain old equality bound. + if !trait_is_same_or_supertrait(cx, did, trait_did) { + return false + } let last = path.segments.last_mut().unwrap(); - let bindings = match last.params { - PP::AngleBracketed { ref mut bindings, .. } => bindings, - PP::Parenthesized { .. } => return false, + match last.params { + PP::AngleBracketed { ref mut bindings, .. } => { + bindings.push(clean::TypeBinding { + name: name.clone(), + ty: rhs.clone(), + }); + } + PP::Parenthesized { ref mut output, .. } => { + assert!(output.is_none()); + *output = Some(rhs.clone()); + } }; - bindings.push(clean::TypeBinding { - name: name.clone(), - ty: rhs.clone(), - }); true }) }); @@ -134,3 +148,33 @@ pub fn ty_params(mut params: Vec) -> Vec { fn ty_bounds(bounds: Vec) -> Vec { bounds } + +fn trait_is_same_or_supertrait(cx: &DocContext, child: ast::DefId, + trait_: ast::DefId) -> bool { + if child == trait_ { + return true + } + let def = ty::lookup_trait_def(cx.tcx(), child); + let predicates = ty::lookup_predicates(cx.tcx(), child); + let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); + generics.where_predicates.iter().filter_map(|pred| { + match *pred { + clean::WherePredicate::BoundPredicate { + ty: clean::Generic(ref s), + ref bounds + } if *s == "Self" => Some(bounds), + _ => None, + } + }).flat_map(|bounds| bounds.iter()).any(|bound| { + let poly_trait = match *bound { + clean::TraitBound(ref t, _) => t, + _ => return false, + }; + match poly_trait.trait_ { + clean::ResolvedPath { did, .. } => { + trait_is_same_or_supertrait(cx, did, trait_) + } + _ => false, + } + }) +} diff --git a/src/test/auxiliary/issue-21801.rs b/src/test/auxiliary/issue-21801.rs new file mode 100644 index 0000000000000000000000000000000000000000..ada6c6925025de6c81e1f403ea1a28bab0b577c4 --- /dev/null +++ b/src/test/auxiliary/issue-21801.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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. + +pub struct Foo; + +impl Foo { + pub fn new(f: F) -> Foo where F: FnMut() -> i32 { + loop {} + } +} diff --git a/src/test/rustdoc/issue-21801.rs b/src/test/rustdoc/issue-21801.rs new file mode 100644 index 0000000000000000000000000000000000000000..00b46638b299c0e93f95b834d09eb1e50e5886f9 --- /dev/null +++ b/src/test/rustdoc/issue-21801.rs @@ -0,0 +1,18 @@ +// Copyright 2015 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. + +// aux-build:issue-21801.rs + +extern crate issue_21801; + +// @has issue_21801/struct.Foo.html +// @has - '//*[@id="method.new"]' \ +// 'fn new(f: F) -> Foo where F: FnMut() -> i32' +pub use issue_21801::Foo;