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:
parent
d7fcee8347
commit
6950f68870
|
@ -958,7 +958,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
|
||||||
Generics {
|
Generics {
|
||||||
type_params: simplify::ty_params(stripped_typarams),
|
type_params: simplify::ty_params(stripped_typarams),
|
||||||
lifetimes: stripped_lifetimes,
|
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::mem;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use clean;
|
use rustc::middle::subst;
|
||||||
use clean::WherePredicate as WP;
|
use rustc::middle::ty;
|
||||||
use clean::PathParameters as PP;
|
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
|
// First, partition the where clause into its separate components
|
||||||
let mut params = HashMap::new();
|
let mut params = HashMap::new();
|
||||||
let mut lifetimes = Vec::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),
|
clean::ResolvedPath { did, ref mut path, ..} => (did, path),
|
||||||
_ => return false,
|
_ => 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 last = path.segments.last_mut().unwrap();
|
||||||
let bindings = match last.params {
|
match last.params {
|
||||||
PP::AngleBracketed { ref mut bindings, .. } => bindings,
|
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||||
PP::Parenthesized { .. } => return false,
|
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
|
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> {
|
fn ty_bounds(bounds: Vec<clean::TyParamBound>) -> Vec<clean::TyParamBound> {
|
||||||
bounds
|
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,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
Loading…
Reference in New Issue