Skip to content
Merged
6 changes: 6 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,12 @@ impl Item {
self.stability.as_ref().map(|s| &s.since[..])
}

pub fn is_non_exhaustive(&self) -> bool {
self.attrs.other_attrs.iter()
.filter(|a| a.name().as_str() == "non_exhaustive")
.count() > 0
Copy link
Contributor

@frewsxcv frewsxcv Jul 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be more peformant to use .any() instead of .count() > 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this.

}

/// Returns a documentation-level item type from the item.
pub fn type_(&self) -> ItemType {
ItemType::from(self)
Expand Down
11 changes: 10 additions & 1 deletion src/librustdoc/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ 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,
} = item;

let inner = match inner {
StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
Expand Down
40 changes: 37 additions & 3 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,35 @@ fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item)
Ok(())
}

fn document_non_exhaustive_header(item: &clean::Item) -> &str {
if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" }
}

fn document_non_exhaustive(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
if item.is_non_exhaustive() {
write!(w, "<p class='non-exhaustive'>")?;

if item.is_struct() {
write!(w, "This struct is marked as non-exhaustive as additional fields may be \
added in the future. This means that this struct cannot be constructed in \
external crates using the traditional <code>Struct {{ .. }}</code> syntax;
cannot be matched against without a wildcard <code>..</code>; and \
functional-record-updates do not work on this struct.")?;
} else if item.is_enum() {
write!(w, "This enum is marked as non-exhaustive, and additional variants may be \
added in the future. When matching over values of this type, an extra \
<code>_</code> arm must be added to account for future extensions.")?;
} else {
write!(w, "This type will require a wildcard arm in any match statements or \
constructors.")?;
}

write!(w, "</p>")?;
}

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);
Expand Down Expand Up @@ -3122,7 +3151,9 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
if let doctree::Plain = s.struct_type {
if fields.peek().is_some() {
write!(w, "<h2 id='fields' class='fields small-section-header'>
Fields<a href='#fields' class='anchor'></a></h2>")?;
Fields{}<a href='#fields' class='anchor'></a></h2>",
document_non_exhaustive_header(it))?;
document_non_exhaustive(w, it)?;
for (field, ty) in fields {
let id = derive_id(format!("{}.{}",
ItemType::StructField,
Expand Down Expand Up @@ -3254,7 +3285,9 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
document(w, cx, it)?;
if !e.variants.is_empty() {
write!(w, "<h2 id='variants' class='variants small-section-header'>
Variants<a href='#variants' class='anchor'></a></h2>\n")?;
Variants{}<a href='#variants' class='anchor'></a></h2>\n",
document_non_exhaustive_header(it))?;
document_non_exhaustive(w, it)?;
for variant in &e.variants {
let id = derive_id(format!("{}.{}",
ItemType::Variant,
Expand Down Expand Up @@ -3355,7 +3388,8 @@ const ATTRIBUTE_WHITELIST: &'static [&'static str] = &[
"must_use",
"no_mangle",
"repr",
"unsafe_destructor_blind_to_params"
"unsafe_destructor_blind_to_params",
"non_exhaustive"
];

fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
Expand Down
4 changes: 3 additions & 1 deletion src/librustdoc/html/static/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ pre {
.content .fnname{ color: #2BAB63; }
.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }

.non-exhaustive { color: #DDD; margin-bottom: 1em; }

pre.rust .comment { color: #8d8d8b; }
pre.rust .doccomment { color: #8ca375; }

Expand Down Expand Up @@ -406,4 +408,4 @@ kbd {
}
.search-results td span.grey {
color: #ccc;
}
}
4 changes: 3 additions & 1 deletion src/librustdoc/html/static/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ pre {
.content .fnname { color: #9a6e31; }
.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }

.non-exhaustive { color: #222; margin-bottom: 1em; }

pre.rust .comment { color: #8E908C; }
pre.rust .doccomment { color: #4D4D4C; }

Expand Down Expand Up @@ -400,4 +402,4 @@ kbd {
}
.search-results td span.grey {
color: #999;
}
}