提交 6950f688 编写于 作者: A Alex Crichton

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
上级 d7fcee83
......@@ -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),
}
}
}
......
......@@ -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<WP>) -> Vec<WP> {
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());
}
};
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,
}
})
}
// 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 {}
}
}
// 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;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册