diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c51c8027de64e..4819256a54550 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -508,6 +508,18 @@ impl Item { .as_ref() .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) } + pub fn is_default(&self) -> bool { + match self.inner { + ItemEnum::MethodItem(ref meth) => { + if let Some(defaultness) = meth.defaultness { + defaultness.has_value() && !defaultness.is_final() + } else { + false + } + } + _ => false, + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -1700,9 +1712,11 @@ pub struct Method { pub generics: Generics, pub decl: FnDecl, pub header: hir::FnHeader, + pub defaultness: Option, } -impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { +impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId, + Option) { fn clean(&self, cx: &DocContext<'_>) -> Method { let (generics, decl) = enter_impl_trait(cx, || { (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)) @@ -1711,6 +1725,7 @@ impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) decl, generics, header: self.0.header, + defaultness: self.3, } } } @@ -2016,7 +2031,7 @@ impl Clean for hir::TraitItem { default.map(|e| print_const_expr(cx, e))) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { - MethodItem((sig, &self.generics, body).clean(cx)) + MethodItem((sig, &self.generics, body, None).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { @@ -2054,7 +2069,7 @@ impl Clean for hir::ImplItem { Some(print_const_expr(cx, expr))) } hir::ImplItemKind::Method(ref sig, body) => { - MethodItem((sig, &self.generics, body).clean(cx)) + MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { type_: ty.clean(cx), @@ -2137,7 +2152,8 @@ impl<'tcx> Clean for ty::AssociatedItem { abi: sig.abi(), constness, asyncness: hir::IsAsync::NotAsync, - } + }, + defaultness: Some(self.defaultness), }) } else { TyMethodItem(TyMethod { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index d204a179ca62c..48baf27bae20a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -45,6 +45,7 @@ pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); /// Wrapper struct for emitting a comma-separated list of items pub struct CommaSep<'a, T>(pub &'a [T]); pub struct AbiSpace(pub Abi); +pub struct DefaultSpace(pub bool); /// Wrapper struct for properly emitting a function or method declaration. pub struct Function<'a> { @@ -1057,3 +1058,13 @@ impl fmt::Display for AbiSpace { } } } + +impl fmt::Display for DefaultSpace { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0 { + write!(f, "default ") + } else { + Ok(()) + } + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b3a816d17f56c..a262a2f28853c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -61,7 +61,7 @@ use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; use crate::html::format::{AsyncSpace, ConstnessSpace}; -use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace}; +use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; use crate::html::item_type::ItemType; @@ -3429,11 +3429,12 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>, } }; let mut header_len = format!( - "{}{}{}{}{:#}fn {}{:#}", + "{}{}{}{}{}{:#}fn {}{:#}", VisSpace(&meth.visibility), ConstnessSpace(header.constness), UnsafetySpace(header.unsafety), AsyncSpace(header.asyncness), + DefaultSpace(meth.is_default()), AbiSpace(header.abi), name, *g @@ -3445,12 +3446,13 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>, (0, true) }; render_attributes(w, meth)?; - write!(w, "{}{}{}{}{}fn {name}\ + write!(w, "{}{}{}{}{}{}fn {name}\ {generics}{decl}{where_clause}", VisSpace(&meth.visibility), ConstnessSpace(header.constness), UnsafetySpace(header.unsafety), AsyncSpace(header.asyncness), + DefaultSpace(meth.is_default()), AbiSpace(header.abi), href = href, name = name, diff --git a/src/test/rustdoc/default_trait_method.rs b/src/test/rustdoc/default_trait_method.rs new file mode 100644 index 0000000000000..dfbd8f2210fa4 --- /dev/null +++ b/src/test/rustdoc/default_trait_method.rs @@ -0,0 +1,15 @@ +#![feature(specialization)] + +pub trait Item { + fn foo(); + fn bar(); +} + +// @has default_trait_method/trait.Item.html +// @has - '//*[@id="method.foo"]' 'default fn foo()' +// @has - '//*[@id="method.bar"]' 'fn bar()' +// @!has - '//*[@id="method.bar"]' 'default fn bar()' +impl Item for T { + default fn foo() {} + fn bar() {} +}