From: Oliver Middleton Date: Wed, 29 Nov 2017 22:05:38 +0000 (+0000) Subject: rustdoc: Fix issues with cross-crate inlined associated items X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=b4448435f95ab62cc2017996f60cdb27ea212d32;p=rust.git rustdoc: Fix issues with cross-crate inlined associated items * Visibility was missing from impl items. * Attributes and docs were missing from consts and types in impls. * Const default values were missing from traits. This unifies the code that handles associated items from impls and traits. --- diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 820c3e856db..85c1796ecef 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -332,74 +332,10 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { let predicates = tcx.predicates_of(did); let trait_items = tcx.associated_items(did).filter_map(|item| { - match item.kind { - ty::AssociatedKind::Const => { - let default = if item.defaultness.has_value() { - Some(print_inlined_const(cx, item.def_id)) - } else { - None - }; - Some(clean::Item { - name: Some(item.name.clean(cx)), - inner: clean::AssociatedConstItem( - tcx.type_of(item.def_id).clean(cx), - default, - ), - source: tcx.def_span(item.def_id).clean(cx), - attrs: clean::Attributes::default(), - visibility: None, - stability: tcx.lookup_stability(item.def_id).clean(cx), - deprecation: tcx.lookup_deprecation(item.def_id).clean(cx), - def_id: item.def_id - }) - } - ty::AssociatedKind::Method => { - if item.vis != ty::Visibility::Public && associated_trait.is_none() { - return None - } - let mut cleaned = item.clean(cx); - cleaned.inner = match cleaned.inner.clone() { - clean::TyMethodItem(clean::TyMethod { - unsafety, decl, generics, abi - }) => { - let constness = if tcx.is_const_fn(item.def_id) { - hir::Constness::Const - } else { - hir::Constness::NotConst - }; - - clean::MethodItem(clean::Method { - unsafety, - constness, - decl, - generics, - abi, - }) - } - ref r => panic!("not a tymethod: {:?}", r), - }; - Some(cleaned) - } - ty::AssociatedKind::Type => { - let typedef = clean::Typedef { - type_: tcx.type_of(item.def_id).clean(cx), - generics: clean::Generics { - lifetimes: vec![], - type_params: vec![], - where_predicates: vec![] - } - }; - Some(clean::Item { - name: Some(item.name.clean(cx)), - inner: clean::TypedefItem(typedef, true), - source: tcx.def_span(item.def_id).clean(cx), - attrs: clean::Attributes::default(), - visibility: None, - stability: tcx.lookup_stability(item.def_id).clean(cx), - deprecation: tcx.lookup_deprecation(item.def_id).clean(cx), - def_id: item.def_id - }) - } + if associated_trait.is_some() || item.vis == ty::Visibility::Public { + Some(item.clean(cx)) + } else { + None } }).collect::>(); let polarity = tcx.impl_polarity(did); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 538737e7fe4..be7bd3d5510 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1595,7 +1595,12 @@ fn clean(&self, cx: &DocContext) -> Item { let inner = match self.kind { ty::AssociatedKind::Const => { let ty = cx.tcx.type_of(self.def_id); - AssociatedConstItem(ty.clean(cx), None) + let default = if self.defaultness.has_value() { + Some(inline::print_inlined_const(cx, self.def_id)) + } else { + None + }; + AssociatedConstItem(ty.clean(cx), default) } ty::AssociatedKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), @@ -1626,18 +1631,21 @@ fn clean(&self, cx: &DocContext) -> Item { } let provided = match self.container { - ty::ImplContainer(_) => false, + ty::ImplContainer(_) => true, ty::TraitContainer(_) => self.defaultness.has_value() }; if provided { + let constness = if cx.tcx.is_const_fn(self.def_id) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; MethodItem(Method { unsafety: sig.unsafety(), generics, decl, abi: sig.abi(), - - // trait methods cannot (currently, at least) be const - constness: hir::Constness::NotConst, + constness, }) } else { TyMethodItem(TyMethod { @@ -1651,14 +1659,14 @@ fn clean(&self, cx: &DocContext) -> Item { ty::AssociatedKind::Type => { let my_name = self.name.clean(cx); - let mut bounds = if let ty::TraitContainer(did) = self.container { + if let ty::TraitContainer(did) = self.container { // When loading a cross-crate associated type, the bounds for this type // are actually located on the trait/impl itself, so we need to load // all of the generics from there and then look for bounds that are // applied to this associated type in question. let predicates = cx.tcx.predicates_of(did); let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); - generics.where_predicates.iter().filter_map(|pred| { + let mut bounds = generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { ty: QPath { ref name, ref self_type, ref trait_ }, @@ -1676,34 +1684,45 @@ fn clean(&self, cx: &DocContext) -> Item { _ => return None, } Some(bounds) - }).flat_map(|i| i.iter().cloned()).collect::>() - } else { - vec![] - }; + }).flat_map(|i| i.iter().cloned()).collect::>(); + // Our Sized/?Sized bound didn't get handled when creating the generics + // because we didn't actually get our whole set of bounds until just now + // (some of them may have come from the trait). If we do have a sized + // bound, we remove it, and if we don't then we add the `?Sized` bound + // at the end. + match bounds.iter().position(|b| b.is_sized_bound(cx)) { + Some(i) => { bounds.remove(i); } + None => bounds.push(TyParamBound::maybe_sized(cx)), + } - // Our Sized/?Sized bound didn't get handled when creating the generics - // because we didn't actually get our whole set of bounds until just now - // (some of them may have come from the trait). If we do have a sized - // bound, we remove it, and if we don't then we add the `?Sized` bound - // at the end. - match bounds.iter().position(|b| b.is_sized_bound(cx)) { - Some(i) => { bounds.remove(i); } - None => bounds.push(TyParamBound::maybe_sized(cx)), - } + let ty = if self.defaultness.has_value() { + Some(cx.tcx.type_of(self.def_id)) + } else { + None + }; - let ty = if self.defaultness.has_value() { - Some(cx.tcx.type_of(self.def_id)) + AssociatedTypeItem(bounds, ty.clean(cx)) } else { - None - }; - - AssociatedTypeItem(bounds, ty.clean(cx)) + TypedefItem(Typedef { + type_: cx.tcx.type_of(self.def_id).clean(cx), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new(), + }, + }, true) + } } }; + let visibility = match self.container { + ty::ImplContainer(_) => self.vis.clean(cx), + ty::TraitContainer(_) => None, + }; + Item { name: Some(self.name.clean(cx)), - visibility: Some(Inherited), + visibility, stability: get_stability(cx, self.def_id), deprecation: get_deprecation(cx, self.def_id), def_id: self.def_id, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index cf557b1c661..b8a0b334b86 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2621,7 +2621,8 @@ fn assoc_const(w: &mut fmt::Formatter, ty: &clean::Type, _default: Option<&String>, link: AssocItemLink) -> fmt::Result { - write!(w, "const {}: {}", + write!(w, "{}const {}: {}", + VisSpace(&it.visibility), naive_assoc_href(it, link), it.name.as_ref().unwrap(), ty)?; diff --git a/src/test/rustdoc/inline_cross/assoc-items.rs b/src/test/rustdoc/inline_cross/assoc-items.rs new file mode 100644 index 00000000000..95d936883ff --- /dev/null +++ b/src/test/rustdoc/inline_cross/assoc-items.rs @@ -0,0 +1,57 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:assoc-items.rs +// build-aux-docs +// ignore-cross-compile + +#![crate_name = "foo"] + +extern crate assoc_items; + +// @has foo/struct.MyStruct.html +// @!has - 'PrivateConst' +// @has - '//*[@id="associatedconstant.PublicConst"]' 'pub const PublicConst: u8' +// @has - '//*[@class="docblock"]' 'PublicConst: u8 = 123' +// @has - '//*[@class="docblock"]' 'docs for PublicConst' +// @!has - 'private_method' +// @has - '//*[@id="method.public_method"]' 'pub fn public_method()' +// @has - '//*[@class="docblock"]' 'docs for public_method' +// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16' +// @has - '//*[@class="docblock"]' 'ConstNoDefault: i16 = -123' +// @has - '//*[@class="docblock"]' 'dox for ConstNoDefault' +// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16' +// @has - '//*[@class="docblock"]' 'ConstWithDefault: u16 = 12345' +// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault' +// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault = i32' +// @has - '//*[@class="docblock"]' 'dox for TypeNoDefault' +// @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32' +// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault' +// @has - '//*[@id="method.method_no_default"]' 'fn method_no_default()' +// @has - '//*[@class="docblock"]' 'dox for method_no_default' +// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()' +// @has - '//*[@class="docblock"]' 'docs for method_with_default' +pub use assoc_items::MyStruct; + +// @has foo/trait.MyTrait.html +// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16' +// @has - '//*[@class="docblock"]' 'docs for ConstNoDefault' +// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16' +// @has - '//*[@class="docblock"]' 'ConstWithDefault: u16 = 12345' +// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault' +// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault' +// @has - '//*[@class="docblock"]' 'docs for TypeNoDefault' +// @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32' +// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault' +// @has - '//*[@id="tymethod.method_no_default"]' 'fn method_no_default()' +// @has - '//*[@class="docblock"]' 'docs for method_no_default' +// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()' +// @has - '//*[@class="docblock"]' 'docs for method_with_default' +pub use assoc_items::MyTrait; diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs new file mode 100644 index 00000000000..e955526900e --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs @@ -0,0 +1,48 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_type_defaults)] + +pub struct MyStruct; + +impl MyStruct { + /// docs for PrivateConst + const PrivateConst: i8 = -123; + /// docs for PublicConst + pub const PublicConst: u8 = 123; + /// docs for private_method + fn private_method() {} + /// docs for public_method + pub fn public_method() {} +} + +pub trait MyTrait { + /// docs for ConstNoDefault + const ConstNoDefault: i16; + /// docs for ConstWithDefault + const ConstWithDefault: u16 = 12345; + /// docs for TypeNoDefault + type TypeNoDefault; + /// docs for TypeWithDefault + type TypeWithDefault = u32; + /// docs for method_no_default + fn method_no_default(); + /// docs for method_with_default + fn method_with_default() {} +} + +impl MyTrait for MyStruct { + /// dox for ConstNoDefault + const ConstNoDefault: i16 = -12345; + /// dox for TypeNoDefault + type TypeNoDefault = i32; + /// dox for method_no_default + fn method_no_default() {} +}