rustdoc: Simplify predicates with paren notation

This change is aimed at improving cross-crate (inlined) notation of generic
closures. The change modifies `simplify::where_predicates` to handle
parenthesized notation as well as starting to handle supertrait bounds as well.
This was necessary because all output constraints of closures are bound to
`FnOnce` but most trait bounds are that of `FnMut`.

Close #21801
This commit is contained in:
Alex Crichton 2015-04-07 12:20:24 -07:00
parent d7fcee8347
commit 6950f68870
4 changed files with 92 additions and 13 deletions

View File

@ -958,7 +958,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
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),
}
}
}

View File

@ -29,11 +29,16 @@
use std::mem;
use std::collections::HashMap;
use clean;
use clean::WherePredicate as WP;
use clean::PathParameters as PP;
use rustc::middle::subst;
use rustc::middle::ty;
use syntax::ast;
pub fn where_clauses(clauses: Vec<WP>) -> Vec<WP> {
use clean::PathParameters as PP;
use clean::WherePredicate as WP;
use clean::{self, Clean};
use core::DocContext;
pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
// 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<WP>) -> Vec<WP> {
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<clean::TyParam>) -> Vec<clean::TyParam> {
fn ty_bounds(bounds: Vec<clean::TyParamBound>) -> Vec<clean::TyParamBound> {
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,
}
})
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: F) -> Foo where F: FnMut() -> i32 {
loop {}
}
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: F) -> Foo where F: FnMut() -> i32'
pub use issue_21801::Foo;