Skip to content

Commit 6950f68

Browse files
committed
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
1 parent d7fcee8 commit 6950f68

File tree

4 files changed

+91
-12
lines changed

4 files changed

+91
-12
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
958958
Generics {
959959
type_params: simplify::ty_params(stripped_typarams),
960960
lifetimes: stripped_lifetimes,
961-
where_predicates: simplify::where_clauses(where_predicates),
961+
where_predicates: simplify::where_clauses(cx, where_predicates),
962962
}
963963
}
964964
}

src/librustdoc/clean/simplify.rs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,16 @@
2929
use std::mem;
3030
use std::collections::HashMap;
3131

32-
use clean;
33-
use clean::WherePredicate as WP;
32+
use rustc::middle::subst;
33+
use rustc::middle::ty;
34+
use syntax::ast;
35+
3436
use clean::PathParameters as PP;
37+
use clean::WherePredicate as WP;
38+
use clean::{self, Clean};
39+
use core::DocContext;
3540

36-
pub fn where_clauses(clauses: Vec<WP>) -> Vec<WP> {
41+
pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
3742
// First, partition the where clause into its separate components
3843
let mut params = HashMap::new();
3944
let mut lifetimes = Vec::new();
@@ -90,16 +95,25 @@ pub fn where_clauses(clauses: Vec<WP>) -> Vec<WP> {
9095
clean::ResolvedPath { did, ref mut path, ..} => (did, path),
9196
_ => return false,
9297
};
93-
if did != trait_did { return false }
98+
// If this QPath's trait `trait_did` is the same as, or a supertrait
99+
// of, the bound's trait `did` then we can keep going, otherwise
100+
// this is just a plain old equality bound.
101+
if !trait_is_same_or_supertrait(cx, did, trait_did) {
102+
return false
103+
}
94104
let last = path.segments.last_mut().unwrap();
95-
let bindings = match last.params {
96-
PP::AngleBracketed { ref mut bindings, .. } => bindings,
97-
PP::Parenthesized { .. } => return false,
105+
match last.params {
106+
PP::AngleBracketed { ref mut bindings, .. } => {
107+
bindings.push(clean::TypeBinding {
108+
name: name.clone(),
109+
ty: rhs.clone(),
110+
});
111+
}
112+
PP::Parenthesized { ref mut output, .. } => {
113+
assert!(output.is_none());
114+
*output = Some(rhs.clone());
115+
}
98116
};
99-
bindings.push(clean::TypeBinding {
100-
name: name.clone(),
101-
ty: rhs.clone(),
102-
});
103117
true
104118
})
105119
});
@@ -134,3 +148,33 @@ pub fn ty_params(mut params: Vec<clean::TyParam>) -> Vec<clean::TyParam> {
134148
fn ty_bounds(bounds: Vec<clean::TyParamBound>) -> Vec<clean::TyParamBound> {
135149
bounds
136150
}
151+
152+
fn trait_is_same_or_supertrait(cx: &DocContext, child: ast::DefId,
153+
trait_: ast::DefId) -> bool {
154+
if child == trait_ {
155+
return true
156+
}
157+
let def = ty::lookup_trait_def(cx.tcx(), child);
158+
let predicates = ty::lookup_predicates(cx.tcx(), child);
159+
let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
160+
generics.where_predicates.iter().filter_map(|pred| {
161+
match *pred {
162+
clean::WherePredicate::BoundPredicate {
163+
ty: clean::Generic(ref s),
164+
ref bounds
165+
} if *s == "Self" => Some(bounds),
166+
_ => None,
167+
}
168+
}).flat_map(|bounds| bounds.iter()).any(|bound| {
169+
let poly_trait = match *bound {
170+
clean::TraitBound(ref t, _) => t,
171+
_ => return false,
172+
};
173+
match poly_trait.trait_ {
174+
clean::ResolvedPath { did, .. } => {
175+
trait_is_same_or_supertrait(cx, did, trait_)
176+
}
177+
_ => false,
178+
}
179+
})
180+
}

src/test/auxiliary/issue-21801.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub struct Foo;
12+
13+
impl Foo {
14+
pub fn new<F>(f: F) -> Foo where F: FnMut() -> i32 {
15+
loop {}
16+
}
17+
}

src/test/rustdoc/issue-21801.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:issue-21801.rs
12+
13+
extern crate issue_21801;
14+
15+
// @has issue_21801/struct.Foo.html
16+
// @has - '//*[@id="method.new"]' \
17+
// 'fn new<F>(f: F) -> Foo where F: FnMut() -> i32'
18+
pub use issue_21801::Foo;

0 commit comments

Comments
 (0)