Rollup merge of #49427 - Manishearth:rustdoc-impl-trait-extern, r=GuillaumeGomez
Correctly handle impl trait in external items in rustdoc fixes #49373 r? @QuietMisdreavus
This commit is contained in:
commit
6ca14660af
3 changed files with 117 additions and 10 deletions
|
|
@ -1380,17 +1380,18 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
|
||||
impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
|
||||
let path = external_path(cx, &cx.tcx.item_name(self.def_id),
|
||||
Some(self.def_id), true, vec![], self.substs);
|
||||
let (trait_ref, ref bounds) = *self;
|
||||
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
|
||||
let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id),
|
||||
Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
|
||||
|
||||
debug!("ty::TraitRef\n subst: {:?}\n", self.substs);
|
||||
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
|
||||
|
||||
// collect any late bound regions
|
||||
let mut late_bounds = vec![];
|
||||
for ty_s in self.input_types().skip(1) {
|
||||
for ty_s in trait_ref.input_types().skip(1) {
|
||||
if let ty::TyTuple(ts) = ty_s.sty {
|
||||
for &ty_s in ts {
|
||||
if let ty::TyRef(ref reg, _) = ty_s.sty {
|
||||
|
|
@ -1410,7 +1411,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
|
|||
trait_: ResolvedPath {
|
||||
path,
|
||||
typarams: None,
|
||||
did: self.def_id,
|
||||
did: trait_ref.def_id,
|
||||
is_generic: false,
|
||||
},
|
||||
generic_params: late_bounds,
|
||||
|
|
@ -1420,6 +1421,12 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
(self, vec![]).clean(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
|
||||
let mut v = Vec::new();
|
||||
|
|
@ -2780,9 +2787,51 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
let predicates_of = cx.tcx.predicates_of(def_id);
|
||||
let substs = cx.tcx.lift(&substs).unwrap();
|
||||
let bounds = predicates_of.instantiate(cx.tcx, substs);
|
||||
ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
|
||||
predicate.to_opt_poly_trait_ref().clean(cx)
|
||||
}).collect())
|
||||
let mut regions = vec![];
|
||||
let mut has_sized = false;
|
||||
let mut bounds = bounds.predicates.iter().filter_map(|predicate| {
|
||||
let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
|
||||
tr
|
||||
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
|
||||
// these should turn up at the end
|
||||
pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r)));
|
||||
return None;
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
|
||||
if trait_ref.def_id() == sized {
|
||||
has_sized = true;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let bounds = bounds.predicates.iter().filter_map(|pred|
|
||||
if let ty::Predicate::Projection(proj) = *pred {
|
||||
let proj = proj.skip_binder();
|
||||
if proj.projection_ty.trait_ref(cx.tcx) == *trait_ref.skip_binder() {
|
||||
Some(TypeBinding {
|
||||
name: cx.tcx.associated_item(proj.projection_ty.item_def_id)
|
||||
.name.clean(cx),
|
||||
ty: proj.ty.clean(cx),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
).collect();
|
||||
|
||||
Some((trait_ref.skip_binder(), bounds).clean(cx))
|
||||
}).collect::<Vec<_>>();
|
||||
bounds.extend(regions);
|
||||
if !has_sized && !bounds.is_empty() {
|
||||
bounds.insert(0, TyParamBound::maybe_sized(cx));
|
||||
}
|
||||
ImplTrait(bounds)
|
||||
}
|
||||
|
||||
ty::TyClosure(..) | ty::TyGenerator(..) => Tuple(vec![]), // FIXME(pcwalton)
|
||||
|
|
|
|||
37
src/test/rustdoc/auxiliary/extern-impl-trait.rs
Normal file
37
src/test/rustdoc/auxiliary/extern-impl-trait.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2018 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 trait Foo {
|
||||
type Associated;
|
||||
}
|
||||
|
||||
pub struct X;
|
||||
pub struct Y;
|
||||
|
||||
|
||||
impl Foo for X {
|
||||
type Associated = ();
|
||||
}
|
||||
|
||||
impl Foo for Y {
|
||||
type Associated = ();
|
||||
}
|
||||
|
||||
impl X {
|
||||
pub fn returns_sized<'a>(&'a self) -> impl Foo<Associated=()> + 'a {
|
||||
X
|
||||
}
|
||||
}
|
||||
|
||||
impl Y {
|
||||
pub fn returns_unsized<'a>(&'a self) -> Box<impl ?Sized + Foo<Associated=()> + 'a> {
|
||||
Box::new(X)
|
||||
}
|
||||
}
|
||||
21
src/test/rustdoc/extern-impl-trait.rs
Normal file
21
src/test/rustdoc/extern-impl-trait.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2018 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:extern-impl-trait.rs
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate extern_impl_trait;
|
||||
|
||||
// @has 'foo/struct.X.html' '//code' "impl Foo<Associated = ()> + 'a"
|
||||
pub use extern_impl_trait::X;
|
||||
|
||||
// @has 'foo/struct.Y.html' '//code' "impl ?Sized + Foo<Associated = ()> + 'a"
|
||||
pub use extern_impl_trait::Y;
|
||||
Loading…
Add table
Add a link
Reference in a new issue