]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Fix issues with cross-crate inlined associated items
authorOliver Middleton <olliemail27@gmail.com>
Wed, 29 Nov 2017 22:05:38 +0000 (22:05 +0000)
committerOliver Middleton <olliemail27@gmail.com>
Wed, 29 Nov 2017 22:05:38 +0000 (22:05 +0000)
* 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.

src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/test/rustdoc/inline_cross/assoc-items.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs [new file with mode: 0644]

index 820c3e856dbb148ed8e137430a4030aa1c78aca5..85c1796ecef399336887e8a4474c3013786e7b59 100644 (file)
@@ -332,74 +332,10 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     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::<Vec<_>>();
     let polarity = tcx.impl_polarity(did);
index 538737e7fe4d9d460e6d16dad8aacd2a4b075f98..be7bd3d5510ef08400bd4284e574ea5a1990d5b0 100644 (file)
@@ -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::<Vec<_>>()
-                } else {
-                    vec![]
-                };
+                    }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
+                    // 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,
index cf557b1c661d6e9d6c35aa9e61763e6e8ae751d8..b8a0b334b86af20737e90696450864717ba00f08 100644 (file)
@@ -2621,7 +2621,8 @@ fn assoc_const(w: &mut fmt::Formatter,
                ty: &clean::Type,
                _default: Option<&String>,
                link: AssocItemLink) -> fmt::Result {
-    write!(w, "const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
+    write!(w, "{}const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
+           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 (file)
index 0000000..95d9368
--- /dev/null
@@ -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 <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: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 (file)
index 0000000..e955526
--- /dev/null
@@ -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 <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(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() {}
+}