diff options
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 5 | ||||
| -rw-r--r-- | src/librustdoc/fold.rs | 11 | ||||
| -rw-r--r-- | src/librustdoc/html/render.rs | 42 | ||||
| -rw-r--r-- | src/librustdoc/html/static/main.js | 23 | ||||
| -rw-r--r-- | src/librustdoc/html/static/rustdoc.css | 6 | ||||
| -rw-r--r-- | src/librustdoc/html/static/themes/dark.css | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/static/themes/light.css | 2 |
7 files changed, 81 insertions, 10 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2bf1f6e553f..e3dc304128f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -496,6 +496,11 @@ impl Item { self.stability.as_ref().map(|s| &s.since[..]) } + pub fn is_non_exhaustive(&self) -> bool { + self.attrs.other_attrs.iter() + .any(|a| a.name().as_str() == "non_exhaustive") + } + /// Returns a documentation-level item type from the item. pub fn type_(&self) -> ItemType { ItemType::from(self) diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 8e8566cbbde..ddc5d56b474 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -92,7 +92,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)), diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3070458d0be..d92405612ea 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2276,6 +2276,37 @@ 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, "<div class='docblock non-exhaustive non-exhaustive-{}'>", { + if item.is_struct() { "struct" } else if item.is_enum() { "enum" } else { "type" } + })?; + + if item.is_struct() { + write!(w, "Non-exhaustive structs could have additional fields added in future. \ + Therefore, non-exhaustive structs cannot be constructed in external crates \ + using the traditional <code>Struct {{ .. }}</code> syntax; cannot be \ + matched against without a wildcard <code>..</code>; and \ + struct update syntax will not work.")?; + } else if item.is_enum() { + write!(w, "Non-exhaustive enums could have additional variants added in future. \ + Therefore, when matching against variants of non-exhaustive enums, an \ + extra wildcard arm must be added to account for any future variants.")?; + } else { + write!(w, "This type will require a wildcard arm in any match statements or \ + constructors.")?; + } + + write!(w, "</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); @@ -3136,7 +3167,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, @@ -3268,7 +3301,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, @@ -3369,7 +3404,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 { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 3bd343c0c0b..62ef5626ee5 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2001,7 +2001,7 @@ onEach(e.getElementsByClassName('associatedconstant'), func); }); - function createToggle(otherMessage, extraClass) { + function createToggle(otherMessage, fontSize, extraClass) { var span = document.createElement('span'); span.className = 'toggle-label'; span.style.display = 'none'; @@ -2009,7 +2009,10 @@ span.innerHTML = ' Expand description'; } else { span.innerHTML = otherMessage; - span.style.fontSize = '20px'; + } + + if (fontSize) { + span.style.fontSize = fontSize; } var mainToggle = toggle.cloneNode(true); @@ -2048,13 +2051,27 @@ } if (e.parentNode.id === "main") { var otherMessage; + var fontSize; var extraClass; + if (hasClass(e, "type-decl")) { + fontSize = "20px"; otherMessage = ' Show declaration'; + } else if (hasClass(e, "non-exhaustive")) { + otherMessage = ' This '; + if (hasClass(e, "non-exhaustive-struct")) { + otherMessage += 'struct'; + } else if (hasClass(e, "non-exhaustive-enum")) { + otherMessage += 'enum'; + } else if (hasClass(e, "non-exhaustive-type")) { + otherMessage += 'type'; + } + otherMessage += ' is marked as non-exhaustive'; } else if (hasClass(e.childNodes[0], "impl-items")) { extraClass = "marg-left"; } - e.parentNode.insertBefore(createToggle(otherMessage, extraClass), e); + + e.parentNode.insertBefore(createToggle(otherMessage, fontSize, extraClass), e); if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") { collapseDocs(e.previousSibling.childNodes[0], "toggle"); } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 575a7ea2792..b689e2fa385 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1358,4 +1358,8 @@ kbd { } #all-types > p { margin: 5px 0; -} \ No newline at end of file +} + +.non-exhaustive { + margin-bottom: 1em; +} diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 649ee0b781e..b4342f47491 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -406,4 +406,4 @@ kbd { } .search-results td span.grey { color: #ccc; -} \ No newline at end of file +} diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 7d9980363de..e84e3cb5663 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -400,4 +400,4 @@ kbd { } .search-results td span.grey { color: #999; -} \ No newline at end of file +} |
