1
Fork 0

Display #[non_exhaustive] in rustdoc on types.

This commit is contained in:
David Wood 2018-06-27 20:50:59 +01:00
parent ed0350e945
commit a074bd7334
No known key found for this signature in database
GPG key ID: 01760B4F9F53F154
8 changed files with 75 additions and 3 deletions

View file

@ -229,6 +229,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
def_id: self.next_def_id(def_id.krate),
stability: None,
deprecation: None,
non_exhaustive: false,
inner: ImplItem(Impl {
unsafety: hir::Unsafety::Normal,
generics: new_generics,

View file

@ -111,6 +111,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
visibility: Some(clean::Public),
stability: cx.tcx.lookup_stability(did).clean(cx),
deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
non_exhaustive: false,
def_id: did,
});
Some(ret)
@ -412,6 +413,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
visibility: Some(clean::Inherited),
stability: tcx.lookup_stability(did).clean(cx),
deprecation: tcx.lookup_deprecation(did).clean(cx),
non_exhaustive: false,
def_id: did,
});
}

View file

@ -192,6 +192,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
visibility: Some(Public),
stability: get_stability(cx, def_id),
deprecation: get_deprecation(cx, def_id),
non_exhaustive: false,
def_id,
inner: PrimitiveItem(prim),
}
@ -204,6 +205,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
visibility: Some(Public),
stability: get_stability(cx, def_id),
deprecation: get_deprecation(cx, def_id),
non_exhaustive: false,
def_id,
inner: KeywordItem(kw),
}
@ -366,6 +368,7 @@ pub struct Item {
pub def_id: DefId,
pub stability: Option<Stability>,
pub deprecation: Option<Deprecation>,
pub non_exhaustive: bool,
}
impl fmt::Debug for Item {
@ -625,6 +628,7 @@ impl Clean<Item> for doctree::Module {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
def_id: cx.tcx.hir.local_def_id(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
@ -2117,6 +2121,7 @@ impl Clean<Item> for doctree::Function {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
def_id: cx.tcx.hir.local_def_id(self.id),
inner: FunctionItem(Function {
decl,
@ -2298,6 +2303,7 @@ impl Clean<Item> for doctree::Trait {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: TraitItem(Trait {
auto: self.is_auto.clean(cx),
unsafety: self.unsafety,
@ -2367,6 +2373,7 @@ impl Clean<Item> for hir::TraitItem {
visibility: None,
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
non_exhaustive: false,
inner,
}
}
@ -2395,6 +2402,7 @@ impl Clean<Item> for hir::ImplItem {
visibility: self.vis.clean(cx),
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
non_exhaustive: false,
inner,
}
}
@ -2541,6 +2549,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
visibility,
stability: get_stability(cx, self.def_id),
deprecation: get_deprecation(cx, self.def_id),
non_exhaustive: false,
def_id: self.def_id,
attrs: inline::load_attrs(cx, self.def_id),
source: cx.tcx.def_span(self.def_id).clean(cx),
@ -3194,6 +3203,7 @@ impl Clean<Item> for hir::StructField {
visibility: self.vis.clean(cx),
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
non_exhaustive: false,
def_id: cx.tcx.hir.local_def_id(self.id),
inner: StructFieldItem(self.ty.clean(cx)),
}
@ -3209,6 +3219,7 @@ impl<'tcx> Clean<Item> for ty::FieldDef {
visibility: self.vis.clean(cx),
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
non_exhaustive: false,
def_id: self.did,
inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
}
@ -3273,6 +3284,7 @@ impl Clean<Vec<Item>> for doctree::Struct {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: self.non_exhaustive,
inner: StructItem(Struct {
struct_type: self.struct_type,
generics: self.generics.clean(cx),
@ -3298,6 +3310,7 @@ impl Clean<Vec<Item>> for doctree::Union {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: UnionItem(Union {
struct_type: self.struct_type,
generics: self.generics.clean(cx),
@ -3350,6 +3363,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: self.non_exhaustive,
inner: EnumItem(Enum {
variants: self.variants.clean(cx),
generics: self.generics.clean(cx),
@ -3375,6 +3389,7 @@ impl Clean<Item> for doctree::Variant {
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
def_id: cx.tcx.hir.local_def_id(self.def.id()),
inner: VariantItem(Variant {
kind: self.def.clean(cx),
@ -3405,6 +3420,7 @@ impl<'tcx> Clean<Item> for ty::VariantDef {
def_id: field.did,
stability: get_stability(cx, field.did),
deprecation: get_deprecation(cx, field.did),
non_exhaustive: false,
inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
}
}).collect()
@ -3420,6 +3436,7 @@ impl<'tcx> Clean<Item> for ty::VariantDef {
inner: VariantItem(Variant { kind: kind }),
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
non_exhaustive: false,
}
}
}
@ -3671,6 +3688,7 @@ impl Clean<Item> for doctree::Typedef {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: TypedefItem(Typedef {
type_: self.ty.clean(cx),
generics: self.gen.clean(cx),
@ -3722,6 +3740,7 @@ impl Clean<Item> for doctree::Static {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: StaticItem(Static {
type_: self.type_.clean(cx),
mutability: self.mutability.clean(cx),
@ -3747,6 +3766,7 @@ impl Clean<Item> for doctree::Constant {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: ConstantItem(Constant {
type_: self.type_.clean(cx),
expr: print_const_expr(cx, self.expr),
@ -3835,6 +3855,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
inner: ImplItem(Impl {
unsafety: self.unsafety,
generics: self.generics.clean(cx),
@ -3921,6 +3942,7 @@ impl Clean<Item> for doctree::ExternCrate {
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
non_exhaustive: false,
inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
}
}
@ -3967,6 +3989,7 @@ impl Clean<Vec<Item>> for doctree::Import {
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
non_exhaustive: false,
inner: ImportItem(inner)
}]
}
@ -4035,6 +4058,7 @@ impl Clean<Item> for hir::ForeignItem {
visibility: self.vis.clean(cx),
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
non_exhaustive: false,
inner,
}
}
@ -4209,6 +4233,7 @@ impl Clean<Item> for doctree::Macro {
visibility: Some(Public),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
non_exhaustive: false,
def_id: self.def_id,
inner: MacroItem(Macro {
source: format!("macro_rules! {} {{\n{}}}",

View file

@ -97,6 +97,7 @@ pub struct Struct {
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub non_exhaustive: bool,
pub id: NodeId,
pub struct_type: StructType,
pub name: Name,
@ -123,6 +124,7 @@ pub struct Enum {
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub non_exhaustive: bool,
pub variants: hir::HirVec<Variant>,
pub generics: hir::Generics,
pub attrs: hir::HirVec<ast::Attribute>,

View file

@ -90,7 +90,17 @@ pub trait DocFolder : Sized {
/// don't override!
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item;
let Item {
attrs,
name,
source,
visibility,
def_id,
inner,
stability,
deprecation,
non_exhaustive
} = item;
let inner = match inner {
StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
@ -98,7 +108,7 @@ pub trait DocFolder : Sized {
};
Some(Item { attrs, name, source, inner, visibility,
stability, deprecation, def_id })
stability, deprecation, non_exhaustive, def_id })
}
fn fold_mod(&mut self, m: Module) -> Module {

View file

@ -2194,6 +2194,7 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
info!("Documenting {}", name);
}
document_stability(w, cx, item)?;
document_non_exhaustive(w, item)?;
let prefix = render_assoc_const_value(item);
document_full(w, item, cx, &prefix)?;
Ok(())
@ -2262,6 +2263,28 @@ fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item)
Ok(())
}
fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
if item.non_exhaustive {
write!(w, r##"
<div class='non-exhaustive'>
<div class='stab non-exhaustive'>
<details>
<summary>
<span class=microscope>🔬</span>
This type is marked as non exhaustive.
</summary>
<p>
This type will require a wildcard arm in any match statements or constructors.
</p>
</details>
</div>
</div>
"##)?;
}
Ok(())
}
fn name_key(name: &str) -> (&str, u64, usize) {
// find number at end
let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1);

View file

@ -188,6 +188,7 @@ a.test-arrow {
border-color: #66afe9;
}
.stab.non-exhaustive { background: #F5F5F5; border-color: #D3D3D3; }
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }

View file

@ -89,6 +89,12 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
.and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id))
}
fn non_exhaustive(&self, id: ast::NodeId) -> bool {
self.cx.tcx.hir.opt_local_def_id(id)
.map(|def_id| self.cx.tcx.has_attr(def_id, "non_exhaustive"))
.unwrap_or(false)
}
pub fn visit(&mut self, krate: &hir::Crate) {
self.attrs = krate.attrs.clone();
@ -119,6 +125,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
vis: item.vis.clone(),
stab: self.stability(item.id),
depr: self.deprecation(item.id),
non_exhaustive: self.non_exhaustive(item.id),
attrs: item.attrs.clone(),
generics: generics.clone(),
fields: sd.fields().iter().cloned().collect(),
@ -162,6 +169,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
vis: it.vis.clone(),
stab: self.stability(it.id),
depr: self.deprecation(it.id),
non_exhaustive: self.non_exhaustive(it.id),
generics: params.clone(),
attrs: it.attrs.clone(),
id: it.id,