diff options
| author | bors <bors@rust-lang.org> | 2018-03-28 05:29:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-03-28 05:29:57 +0000 |
| commit | e58df0d8c5221fa5743587740eb50e4db42c3d1e (patch) | |
| tree | d7996f34294c11ec8b49e61725c0529119530c46 | |
| parent | 59ec9bfc66b86f04b50f00bb32839315f59252ec (diff) | |
| parent | 4800afa5f5982b06d9cf27ae6003b058ca8855c8 (diff) | |
Auto merge of #49304 - sinkuu:impl_trait_rustdoc, r=QuietMisdreavus
Rustdoc support for universal_impl_trait Hides type parameters synthesized by `impl Trait`-in-argument-position, and enables links to trait names. <img alt="before" src="https://user-images.githubusercontent.com/7091080/37831646-a61413c6-2ee9-11e8-8ec2-a6137956d922.png" width="450"/> ↓ <img alt="after" src="https://user-images.githubusercontent.com/7091080/37831657-b2ff0ae6-2ee9-11e8-8797-fdad904782bf.png" width="450"/> Fixes #49309
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 79 | ||||
| -rw-r--r-- | src/librustdoc/core.rs | 3 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 27 | ||||
| -rw-r--r-- | src/test/rustdoc/universal-impl-trait.rs | 46 |
4 files changed, 127 insertions, 28 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73b3ae32cef..42c9d9e52f3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1235,6 +1235,7 @@ pub struct TyParam { pub did: DefId, pub bounds: Vec<TyParamBound>, pub default: Option<Type>, + pub synthetic: Option<hir::SyntheticTyParamKind>, } impl Clean<TyParam> for hir::TyParam { @@ -1244,6 +1245,7 @@ impl Clean<TyParam> for hir::TyParam { did: cx.tcx.hir.local_def_id(self.id), bounds: self.bounds.clean(cx), default: self.default.clean(cx), + synthetic: self.synthetic, } } } @@ -1259,7 +1261,8 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None - } + }, + synthetic: None, } } } @@ -1627,6 +1630,16 @@ pub enum GenericParam { Type(TyParam), } +impl GenericParam { + pub fn is_synthetic_type_param(&self) -> bool { + if let GenericParam::Type(ref t) = *self { + t.synthetic.is_some() + } else { + false + } + } +} + impl Clean<GenericParam> for hir::GenericParam { fn clean(&self, cx: &DocContext) -> GenericParam { match *self { @@ -1759,11 +1772,12 @@ pub struct Method { impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { + let generics = self.1.clean(cx); Method { - generics: self.1.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)), + generics, unsafety: self.0.unsafety, constness: self.0.constness, - decl: (&*self.0.decl, self.2).clean(cx), abi: self.0.abi } } @@ -1788,6 +1802,8 @@ pub struct Function { impl Clean<Item> for doctree::Function { fn clean(&self, cx: &DocContext) -> Item { + let generics = self.generics.clean(cx); + let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx)); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1797,8 +1813,8 @@ impl Clean<Item> for doctree::Function { deprecation: self.depr.clean(cx), def_id: cx.tcx.hir.local_def_id(self.id), inner: FunctionItem(Function { - decl: (&self.decl, self.body).clean(cx), - generics: self.generics.clean(cx), + decl, + generics, unsafety: self.unsafety, constness: self.constness, abi: self.abi, @@ -1883,7 +1899,8 @@ impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) { vec![].into_iter() } else { cx.tcx.fn_arg_names(did).into_iter() - }.peekable(); + }; + FnDecl { output: Return(sig.skip_binder().output().clean(cx)), attrs: Attributes::default(), @@ -2025,10 +2042,13 @@ impl Clean<Item> for hir::TraitItem { MethodItem((sig, &self.generics, body).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { + let generics = self.generics.clean(cx); TyMethodItem(TyMethod { unsafety: sig.unsafety.clone(), - decl: (&*sig.decl, &names[..]).clean(cx), - generics: self.generics.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || { + (&*sig.decl, &names[..]).clean(cx) + }), + generics, abi: sig.abi }) } @@ -2532,6 +2552,12 @@ impl Clean<Type> for hir::Ty { return new_ty; } + if let Def::TyParam(did) = path.def { + if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) { + return ImplTrait(bounds); + } + } + let mut alias = None; if let Def::TyAlias(def_id) = path.def { // Substitute private type aliases @@ -3244,10 +3270,13 @@ pub struct BareFunctionDecl { impl Clean<BareFunctionDecl> for hir::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { + let generic_params = self.generic_params.clean(cx); BareFunctionDecl { unsafety: self.unsafety, - generic_params: self.generic_params.clean(cx), - decl: (&*self.decl, &self.arg_names[..]).clean(cx), + decl: enter_impl_trait(cx, &generic_params, || { + (&*self.decl, &self.arg_names[..]).clean(cx) + }), + generic_params, abi: self.abi, } } @@ -3548,9 +3577,12 @@ impl Clean<Item> for hir::ForeignItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { hir::ForeignItemFn(ref decl, ref names, ref generics) => { + let generics = generics.clean(cx); ForeignFunctionItem(Function { - decl: (&**decl, &names[..]).clean(cx), - generics: generics.clean(cx), + decl: enter_impl_trait(cx, &generics.params, || { + (&**decl, &names[..]).clean(cx) + }), + generics, unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, constness: hir::Constness::NotConst, @@ -3852,6 +3884,29 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec< once(crate_name).chain(relative).collect() } +pub fn enter_impl_trait<F, R>(cx: &DocContext, gps: &[GenericParam], f: F) -> R +where + F: FnOnce() -> R, +{ + let bounds = gps.iter() + .filter_map(|p| { + if let GenericParam::Type(ref tp) = *p { + if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + return Some((tp.did, tp.bounds.clone())); + } + } + + None + }) + .collect::<FxHashMap<DefId, Vec<TyParamBound>>>(); + + let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds); + let r = f(); + assert!(cx.impl_trait_bounds.borrow().is_empty()); + *cx.impl_trait_bounds.borrow_mut() = old_bounds; + r +} + // Start of code copied from rust-clippy pub fn get_trait_def_id(tcx: &TyCtxt, path: &[&str], use_local: bool) -> Option<DefId> { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1e0fafc8d9d..749d7ec126b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -72,6 +72,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>, /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>, + /// Table DefId of `impl Trait` in argument position -> bounds + pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::TyParamBound>>>, pub send_trait: Option<DefId>, pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>, pub all_fake_def_ids: RefCell<FxHashSet<DefId>>, @@ -261,6 +263,7 @@ pub fn run_core(search_paths: SearchPaths, renderinfo: Default::default(), ty_substs: Default::default(), lt_substs: Default::default(), + impl_trait_bounds: Default::default(), mod_ids: Default::default(), send_trait: send_trait, fake_def_ids: RefCell::new(FxHashMap()), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2913ea6a78e..0a7e19fc643 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -148,11 +148,17 @@ impl fmt::Display for clean::GenericParam { impl fmt::Display for clean::Generics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.params.is_empty() { return Ok(()) } + let real_params = self.params + .iter() + .filter(|p| !p.is_synthetic_type_param()) + .collect::<Vec<_>>(); + if real_params.is_empty() { + return Ok(()); + } if f.alternate() { - write!(f, "<{:#}>", CommaSep(&self.params)) + write!(f, "<{:#}>", CommaSep(&real_params)) } else { - write!(f, "<{}>", CommaSep(&self.params)) + write!(f, "<{}>", CommaSep(&real_params)) } } } @@ -575,7 +581,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&CommaSep(&many), f)?; + fmt::Display::fmt(&CommaSep(many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } } @@ -661,18 +667,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } } clean::ImplTrait(ref bounds) => { - write!(f, "impl ")?; - for (i, bound) in bounds.iter().enumerate() { - if i != 0 { - write!(f, " + ")?; - } - if f.alternate() { - write!(f, "{:#}", *bound)?; - } else { - write!(f, "{}", *bound)?; - } - } - Ok(()) + write!(f, "impl {}", TyParamBounds(bounds)) } clean::QPath { ref name, ref self_type, ref trait_ } => { let should_show_cast = match *trait_ { diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs new file mode 100644 index 00000000000..4cf99562c52 --- /dev/null +++ b/src/test/rustdoc/universal-impl-trait.rs @@ -0,0 +1,46 @@ +// 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. + +#![feature(universal_impl_trait)] +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// @has - //pre 'foo(' +// @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Clone\.html"' +// @matches - '_z: .+impl.+trait\.Copy\.html.+, impl.+trait\.Clone\.html' +pub fn foo(_x: impl Clone, _y: i32, _z: (impl Copy, impl Clone)) { +} + +pub trait Trait { + // @has foo/trait.Trait.html + // @has - 'method</a>(' + // @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Debug\.html"' + fn method(&self, _x: impl std::fmt::Debug) { + } +} + +pub struct S<T>(T); + +impl<T> S<T> { + // @has foo/struct.S.html + // @has - 'bar</a>(' + // @matches - '_bar: impl <a class="trait" href="[^"]+/trait\.Copy\.html"' + pub fn bar(_bar: impl Copy) { + } + + // @has - 'baz</a>(' + // @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html' + pub fn baz(_baz: S<impl Clone>) { + } +} + +// @has - 'method</a>(' +// @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Debug\.html"' +impl<T> Trait for S<T> {} |
