Skip to content

Commit a074bd7

Browse files
committed
Display #[non_exhaustive] in rustdoc on types.
1 parent ed0350e commit a074bd7

File tree

8 files changed

+75
-3
lines changed

8 files changed

+75
-3
lines changed

src/librustdoc/clean/auto_trait.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
229229
def_id: self.next_def_id(def_id.krate),
230230
stability: None,
231231
deprecation: None,
232+
non_exhaustive: false,
232233
inner: ImplItem(Impl {
233234
unsafety: hir::Unsafety::Normal,
234235
generics: new_generics,

src/librustdoc/clean/inline.rs

+2
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
111111
visibility: Some(clean::Public),
112112
stability: cx.tcx.lookup_stability(did).clean(cx),
113113
deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
114+
non_exhaustive: false,
114115
def_id: did,
115116
});
116117
Some(ret)
@@ -412,6 +413,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
412413
visibility: Some(clean::Inherited),
413414
stability: tcx.lookup_stability(did).clean(cx),
414415
deprecation: tcx.lookup_deprecation(did).clean(cx),
416+
non_exhaustive: false,
415417
def_id: did,
416418
});
417419
}

src/librustdoc/clean/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
192192
visibility: Some(Public),
193193
stability: get_stability(cx, def_id),
194194
deprecation: get_deprecation(cx, def_id),
195+
non_exhaustive: false,
195196
def_id,
196197
inner: PrimitiveItem(prim),
197198
}
@@ -204,6 +205,7 @@ impl<'a, 'tcx, 'rcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx>
204205
visibility: Some(Public),
205206
stability: get_stability(cx, def_id),
206207
deprecation: get_deprecation(cx, def_id),
208+
non_exhaustive: false,
207209
def_id,
208210
inner: KeywordItem(kw),
209211
}
@@ -366,6 +368,7 @@ pub struct Item {
366368
pub def_id: DefId,
367369
pub stability: Option<Stability>,
368370
pub deprecation: Option<Deprecation>,
371+
pub non_exhaustive: bool,
369372
}
370373

371374
impl fmt::Debug for Item {
@@ -625,6 +628,7 @@ impl Clean<Item> for doctree::Module {
625628
visibility: self.vis.clean(cx),
626629
stability: self.stab.clean(cx),
627630
deprecation: self.depr.clean(cx),
631+
non_exhaustive: false,
628632
def_id: cx.tcx.hir.local_def_id(self.id),
629633
inner: ModuleItem(Module {
630634
is_crate: self.is_crate,
@@ -2117,6 +2121,7 @@ impl Clean<Item> for doctree::Function {
21172121
visibility: self.vis.clean(cx),
21182122
stability: self.stab.clean(cx),
21192123
deprecation: self.depr.clean(cx),
2124+
non_exhaustive: false,
21202125
def_id: cx.tcx.hir.local_def_id(self.id),
21212126
inner: FunctionItem(Function {
21222127
decl,
@@ -2298,6 +2303,7 @@ impl Clean<Item> for doctree::Trait {
22982303
visibility: self.vis.clean(cx),
22992304
stability: self.stab.clean(cx),
23002305
deprecation: self.depr.clean(cx),
2306+
non_exhaustive: false,
23012307
inner: TraitItem(Trait {
23022308
auto: self.is_auto.clean(cx),
23032309
unsafety: self.unsafety,
@@ -2367,6 +2373,7 @@ impl Clean<Item> for hir::TraitItem {
23672373
visibility: None,
23682374
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
23692375
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2376+
non_exhaustive: false,
23702377
inner,
23712378
}
23722379
}
@@ -2395,6 +2402,7 @@ impl Clean<Item> for hir::ImplItem {
23952402
visibility: self.vis.clean(cx),
23962403
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
23972404
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
2405+
non_exhaustive: false,
23982406
inner,
23992407
}
24002408
}
@@ -2541,6 +2549,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
25412549
visibility,
25422550
stability: get_stability(cx, self.def_id),
25432551
deprecation: get_deprecation(cx, self.def_id),
2552+
non_exhaustive: false,
25442553
def_id: self.def_id,
25452554
attrs: inline::load_attrs(cx, self.def_id),
25462555
source: cx.tcx.def_span(self.def_id).clean(cx),
@@ -3194,6 +3203,7 @@ impl Clean<Item> for hir::StructField {
31943203
visibility: self.vis.clean(cx),
31953204
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
31963205
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
3206+
non_exhaustive: false,
31973207
def_id: cx.tcx.hir.local_def_id(self.id),
31983208
inner: StructFieldItem(self.ty.clean(cx)),
31993209
}
@@ -3209,6 +3219,7 @@ impl<'tcx> Clean<Item> for ty::FieldDef {
32093219
visibility: self.vis.clean(cx),
32103220
stability: get_stability(cx, self.did),
32113221
deprecation: get_deprecation(cx, self.did),
3222+
non_exhaustive: false,
32123223
def_id: self.did,
32133224
inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
32143225
}
@@ -3273,6 +3284,7 @@ impl Clean<Vec<Item>> for doctree::Struct {
32733284
visibility: self.vis.clean(cx),
32743285
stability: self.stab.clean(cx),
32753286
deprecation: self.depr.clean(cx),
3287+
non_exhaustive: self.non_exhaustive,
32763288
inner: StructItem(Struct {
32773289
struct_type: self.struct_type,
32783290
generics: self.generics.clean(cx),
@@ -3298,6 +3310,7 @@ impl Clean<Vec<Item>> for doctree::Union {
32983310
visibility: self.vis.clean(cx),
32993311
stability: self.stab.clean(cx),
33003312
deprecation: self.depr.clean(cx),
3313+
non_exhaustive: false,
33013314
inner: UnionItem(Union {
33023315
struct_type: self.struct_type,
33033316
generics: self.generics.clean(cx),
@@ -3350,6 +3363,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
33503363
visibility: self.vis.clean(cx),
33513364
stability: self.stab.clean(cx),
33523365
deprecation: self.depr.clean(cx),
3366+
non_exhaustive: self.non_exhaustive,
33533367
inner: EnumItem(Enum {
33543368
variants: self.variants.clean(cx),
33553369
generics: self.generics.clean(cx),
@@ -3375,6 +3389,7 @@ impl Clean<Item> for doctree::Variant {
33753389
visibility: None,
33763390
stability: self.stab.clean(cx),
33773391
deprecation: self.depr.clean(cx),
3392+
non_exhaustive: false,
33783393
def_id: cx.tcx.hir.local_def_id(self.def.id()),
33793394
inner: VariantItem(Variant {
33803395
kind: self.def.clean(cx),
@@ -3405,6 +3420,7 @@ impl<'tcx> Clean<Item> for ty::VariantDef {
34053420
def_id: field.did,
34063421
stability: get_stability(cx, field.did),
34073422
deprecation: get_deprecation(cx, field.did),
3423+
non_exhaustive: false,
34083424
inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx))
34093425
}
34103426
}).collect()
@@ -3420,6 +3436,7 @@ impl<'tcx> Clean<Item> for ty::VariantDef {
34203436
inner: VariantItem(Variant { kind: kind }),
34213437
stability: get_stability(cx, self.did),
34223438
deprecation: get_deprecation(cx, self.did),
3439+
non_exhaustive: false,
34233440
}
34243441
}
34253442
}
@@ -3671,6 +3688,7 @@ impl Clean<Item> for doctree::Typedef {
36713688
visibility: self.vis.clean(cx),
36723689
stability: self.stab.clean(cx),
36733690
deprecation: self.depr.clean(cx),
3691+
non_exhaustive: false,
36743692
inner: TypedefItem(Typedef {
36753693
type_: self.ty.clean(cx),
36763694
generics: self.gen.clean(cx),
@@ -3722,6 +3740,7 @@ impl Clean<Item> for doctree::Static {
37223740
visibility: self.vis.clean(cx),
37233741
stability: self.stab.clean(cx),
37243742
deprecation: self.depr.clean(cx),
3743+
non_exhaustive: false,
37253744
inner: StaticItem(Static {
37263745
type_: self.type_.clean(cx),
37273746
mutability: self.mutability.clean(cx),
@@ -3747,6 +3766,7 @@ impl Clean<Item> for doctree::Constant {
37473766
visibility: self.vis.clean(cx),
37483767
stability: self.stab.clean(cx),
37493768
deprecation: self.depr.clean(cx),
3769+
non_exhaustive: false,
37503770
inner: ConstantItem(Constant {
37513771
type_: self.type_.clean(cx),
37523772
expr: print_const_expr(cx, self.expr),
@@ -3835,6 +3855,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
38353855
visibility: self.vis.clean(cx),
38363856
stability: self.stab.clean(cx),
38373857
deprecation: self.depr.clean(cx),
3858+
non_exhaustive: false,
38383859
inner: ImplItem(Impl {
38393860
unsafety: self.unsafety,
38403861
generics: self.generics.clean(cx),
@@ -3921,6 +3942,7 @@ impl Clean<Item> for doctree::ExternCrate {
39213942
visibility: self.vis.clean(cx),
39223943
stability: None,
39233944
deprecation: None,
3945+
non_exhaustive: false,
39243946
inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
39253947
}
39263948
}
@@ -3967,6 +3989,7 @@ impl Clean<Vec<Item>> for doctree::Import {
39673989
visibility: self.vis.clean(cx),
39683990
stability: None,
39693991
deprecation: None,
3992+
non_exhaustive: false,
39703993
inner: ImportItem(inner)
39713994
}]
39723995
}
@@ -4035,6 +4058,7 @@ impl Clean<Item> for hir::ForeignItem {
40354058
visibility: self.vis.clean(cx),
40364059
stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
40374060
deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
4061+
non_exhaustive: false,
40384062
inner,
40394063
}
40404064
}
@@ -4209,6 +4233,7 @@ impl Clean<Item> for doctree::Macro {
42094233
visibility: Some(Public),
42104234
stability: self.stab.clean(cx),
42114235
deprecation: self.depr.clean(cx),
4236+
non_exhaustive: false,
42124237
def_id: self.def_id,
42134238
inner: MacroItem(Macro {
42144239
source: format!("macro_rules! {} {{\n{}}}",

src/librustdoc/doctree.rs

+2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub struct Struct {
9797
pub vis: hir::Visibility,
9898
pub stab: Option<attr::Stability>,
9999
pub depr: Option<attr::Deprecation>,
100+
pub non_exhaustive: bool,
100101
pub id: NodeId,
101102
pub struct_type: StructType,
102103
pub name: Name,
@@ -123,6 +124,7 @@ pub struct Enum {
123124
pub vis: hir::Visibility,
124125
pub stab: Option<attr::Stability>,
125126
pub depr: Option<attr::Deprecation>,
127+
pub non_exhaustive: bool,
126128
pub variants: hir::HirVec<Variant>,
127129
pub generics: hir::Generics,
128130
pub attrs: hir::HirVec<ast::Attribute>,

src/librustdoc/fold.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,25 @@ pub trait DocFolder : Sized {
9090

9191
/// don't override!
9292
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
93-
let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item;
93+
let Item {
94+
attrs,
95+
name,
96+
source,
97+
visibility,
98+
def_id,
99+
inner,
100+
stability,
101+
deprecation,
102+
non_exhaustive
103+
} = item;
94104

95105
let inner = match inner {
96106
StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
97107
_ => self.fold_inner_recur(inner),
98108
};
99109

100110
Some(Item { attrs, name, source, inner, visibility,
101-
stability, deprecation, def_id })
111+
stability, deprecation, non_exhaustive, def_id })
102112
}
103113

104114
fn fold_mod(&mut self, m: Module) -> Module {

src/librustdoc/html/render.rs

+23
Original file line numberDiff line numberDiff line change
@@ -2194,6 +2194,7 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
21942194
info!("Documenting {}", name);
21952195
}
21962196
document_stability(w, cx, item)?;
2197+
document_non_exhaustive(w, item)?;
21972198
let prefix = render_assoc_const_value(item);
21982199
document_full(w, item, cx, &prefix)?;
21992200
Ok(())
@@ -2262,6 +2263,28 @@ fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item)
22622263
Ok(())
22632264
}
22642265

2266+
fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
2267+
if item.non_exhaustive {
2268+
write!(w, r##"
2269+
<div class='non-exhaustive'>
2270+
<div class='stab non-exhaustive'>
2271+
<details>
2272+
<summary>
2273+
<span class=microscope>🔬</span>
2274+
This type is marked as non exhaustive.
2275+
</summary>
2276+
<p>
2277+
This type will require a wildcard arm in any match statements or constructors.
2278+
</p>
2279+
</details>
2280+
</div>
2281+
</div>
2282+
"##)?;
2283+
}
2284+
2285+
Ok(())
2286+
}
2287+
22652288
fn name_key(name: &str) -> (&str, u64, usize) {
22662289
// find number at end
22672290
let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1);

src/librustdoc/html/static/themes/light.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ a.test-arrow {
188188
border-color: #66afe9;
189189
}
190190

191+
.stab.non-exhaustive { background: #F5F5F5; border-color: #D3D3D3; }
191192
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
192193
.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
193194
.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
@@ -400,4 +401,4 @@ kbd {
400401
}
401402
.search-results td span.grey {
402403
color: #999;
403-
}
404+
}

src/librustdoc/visit_ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
8989
.and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id))
9090
}
9191

92+
fn non_exhaustive(&self, id: ast::NodeId) -> bool {
93+
self.cx.tcx.hir.opt_local_def_id(id)
94+
.map(|def_id| self.cx.tcx.has_attr(def_id, "non_exhaustive"))
95+
.unwrap_or(false)
96+
}
97+
9298
pub fn visit(&mut self, krate: &hir::Crate) {
9399
self.attrs = krate.attrs.clone();
94100

@@ -119,6 +125,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
119125
vis: item.vis.clone(),
120126
stab: self.stability(item.id),
121127
depr: self.deprecation(item.id),
128+
non_exhaustive: self.non_exhaustive(item.id),
122129
attrs: item.attrs.clone(),
123130
generics: generics.clone(),
124131
fields: sd.fields().iter().cloned().collect(),
@@ -162,6 +169,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
162169
vis: it.vis.clone(),
163170
stab: self.stability(it.id),
164171
depr: self.deprecation(it.id),
172+
non_exhaustive: self.non_exhaustive(it.id),
165173
generics: params.clone(),
166174
attrs: it.attrs.clone(),
167175
id: it.id,

0 commit comments

Comments
 (0)