Skip to content

Commit 6ca1466

Browse files
authored
Rollup merge of rust-lang#49427 - Manishearth:rustdoc-impl-trait-extern, r=GuillaumeGomez
Correctly handle impl trait in external items in rustdoc fixes rust-lang#49373 r? @QuietMisdreavus
2 parents c17ab37 + 33dceaa commit 6ca1466

File tree

3 files changed

+117
-10
lines changed

3 files changed

+117
-10
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,17 +1380,18 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
13801380
}
13811381
}
13821382

1383-
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
1383+
impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
13841384
fn clean(&self, cx: &DocContext) -> TyParamBound {
1385-
inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
1386-
let path = external_path(cx, &cx.tcx.item_name(self.def_id),
1387-
Some(self.def_id), true, vec![], self.substs);
1385+
let (trait_ref, ref bounds) = *self;
1386+
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
1387+
let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id),
1388+
Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
13881389

1389-
debug!("ty::TraitRef\n subst: {:?}\n", self.substs);
1390+
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
13901391

13911392
// collect any late bound regions
13921393
let mut late_bounds = vec![];
1393-
for ty_s in self.input_types().skip(1) {
1394+
for ty_s in trait_ref.input_types().skip(1) {
13941395
if let ty::TyTuple(ts) = ty_s.sty {
13951396
for &ty_s in ts {
13961397
if let ty::TyRef(ref reg, _) = ty_s.sty {
@@ -1410,7 +1411,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
14101411
trait_: ResolvedPath {
14111412
path,
14121413
typarams: None,
1413-
did: self.def_id,
1414+
did: trait_ref.def_id,
14141415
is_generic: false,
14151416
},
14161417
generic_params: late_bounds,
@@ -1420,6 +1421,12 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
14201421
}
14211422
}
14221423

1424+
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
1425+
fn clean(&self, cx: &DocContext) -> TyParamBound {
1426+
(self, vec![]).clean(cx)
1427+
}
1428+
}
1429+
14231430
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
14241431
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
14251432
let mut v = Vec::new();
@@ -2780,9 +2787,51 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
27802787
let predicates_of = cx.tcx.predicates_of(def_id);
27812788
let substs = cx.tcx.lift(&substs).unwrap();
27822789
let bounds = predicates_of.instantiate(cx.tcx, substs);
2783-
ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
2784-
predicate.to_opt_poly_trait_ref().clean(cx)
2785-
}).collect())
2790+
let mut regions = vec![];
2791+
let mut has_sized = false;
2792+
let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
2793+
let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
2794+
tr
2795+
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
2796+
// these should turn up at the end
2797+
pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r)));
2798+
return None;
2799+
} else {
2800+
return None;
2801+
};
2802+
2803+
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
2804+
if trait_ref.def_id() == sized {
2805+
has_sized = true;
2806+
return None;
2807+
}
2808+
}
2809+
2810+
2811+
let bounds = bounds.predicates.iter().filter_map(|pred|
2812+
if let ty::Predicate::Projection(proj) = *pred {
2813+
let proj = proj.skip_binder();
2814+
if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
2815+
Some(TypeBinding {
2816+
name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
2817+
.name.clean(cx),
2818+
ty: proj.ty.clean(cx),
2819+
})
2820+
} else {
2821+
None
2822+
}
2823+
} else {
2824+
None
2825+
}
2826+
).collect();
2827+
2828+
Some((trait_ref.skip_binder(), bounds).clean(cx))
2829+
}).collect::<Vec<_>>();
2830+
bounds.extend(regions);
2831+
if !has_sized && !bounds.is_empty() {
2832+
bounds.insert(0, TyParamBound::maybe_sized(cx));
2833+
}
2834+
ImplTrait(bounds)
27862835
}
27872836

27882837
ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2018 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 trait Foo {
12+
type Associated;
13+
}
14+
15+
pub struct X;
16+
pub struct Y;
17+
18+
19+
impl Foo for X {
20+
type Associated = ();
21+
}
22+
23+
impl Foo for Y {
24+
type Associated = ();
25+
}
26+
27+
impl X {
28+
pub fn returns_sized<'a>(&'a self) -> impl Foo<Associated=()> + 'a {
29+
X
30+
}
31+
}
32+
33+
impl Y {
34+
pub fn returns_unsized<'a>(&'a self) -> Box<impl ?Sized + Foo<Associated=()> + 'a> {
35+
Box::new(X)
36+
}
37+
}

src/test/rustdoc/extern-impl-trait.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 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:extern-impl-trait.rs
12+
13+
#![crate_name = "foo"]
14+
15+
extern crate extern_impl_trait;
16+
17+
// @has 'foo/struct.X.html' '//code' "impl Foo<Associated = ()> + 'a"
18+
pub use extern_impl_trait::X;
19+
20+
// @has 'foo/struct.Y.html' '//code' "impl ?Sized + Foo<Associated = ()> + 'a"
21+
pub use extern_impl_trait::Y;

0 commit comments

Comments
 (0)