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 {
|
||||
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 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,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
17
src/test/auxiliary/issue-21801.rs
Normal file
17
src/test/auxiliary/issue-21801.rs
Normal 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 {}
|
||||
}
|
||||
}
|
18
src/test/rustdoc/issue-21801.rs
Normal file
18
src/test/rustdoc/issue-21801.rs
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user