about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-16 00:13:26 +0000
committerbors <bors@rust-lang.org>2021-01-16 00:13:26 +0000
commit6c869d34ae2d87d21db9892d4dc088639bcbe041 (patch)
tree934fcc1bd4782a3810b643633412ab8649ea58fa
parentfcbd305ee93f49f19313b9bbeaa25ba8837030d9 (diff)
parentf8b1baac113ed85175453e6dad709dbd65836540 (diff)
downloadrust-6c869d34ae2d87d21db9892d4dc088639bcbe041.tar.gz
rust-6c869d34ae2d87d21db9892d4dc088639bcbe041.zip
Auto merge of #81057 - GuillaumeGomez:rollup-yl2kqst, r=GuillaumeGomez
Rollup of 6 pull requests

Successful merges:

 - #77693 (Add test for #59352)
 - #80515 (Improve JS performance by storing length before comparing to it in loops)
 - #81030 (Update mdbook)
 - #81033 (Remove useless `clean::Variant` struct)
 - #81049 (inline: Round word-size cost estimates up)
 - #81054 (Drop a few unneeded borrows)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs10
-rw-r--r--src/librustdoc/clean/mod.rs26
-rw-r--r--src/librustdoc/clean/types.rs13
-rw-r--r--src/librustdoc/fold.rs6
-rw-r--r--src/librustdoc/html/render/mod.rs29
-rw-r--r--src/librustdoc/html/static/main.js98
-rw-r--r--src/librustdoc/html/static/source-script.js8
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/librustdoc/passes/stripper.rs2
-rw-r--r--src/test/codegen/issue-59352.rs18
-rw-r--r--src/test/mir-opt/issues/issue-59352.rs19
-rw-r--r--src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir102
-rw-r--r--src/tools/rustbook/Cargo.toml2
15 files changed, 231 insertions, 112 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 94fb49fd43e..5e5a48ad525 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1973,9 +1973,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21251d3eb9ca5e8ac5b73384ddaa483a9bbc7d7dcd656b1fa8f266634810334a"
+checksum = "b3d948b64449003363127ed6c6139f03273982c3fe97da4cb3dee933e38ce38f"
 dependencies = [
  "ammonia",
  "anyhow",
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 52350c5d078..07e637b88f9 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -382,7 +382,7 @@ impl Inliner<'tcx> {
             // Cost of the var is the size in machine-words, if we know
             // it.
             if let Some(size) = type_size_of(tcx, self.param_env, ty) {
-                cost += (size / ptr_size) as usize;
+                cost += ((size + ptr_size - 1) / ptr_size) as usize;
             } else {
                 cost += UNKNOWN_SIZE_COST;
             }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 4afa6689b92..6177e39ba9e 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -813,10 +813,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if ty.is_never() {
                         None
                     } else {
-                        Some(match &elem.kind {
+                        Some(match elem.kind {
                             // Point at the tail expression when possible.
                             hir::ExprKind::Block(block, _) => {
-                                block.expr.as_ref().map_or(block.span, |e| e.span)
+                                block.expr.map_or(block.span, |e| e.span)
                             }
                             _ => elem.span,
                         })
@@ -824,14 +824,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 })
         };
 
-        if let hir::ExprKind::If(_, _, Some(el)) = &expr.kind {
+        if let hir::ExprKind::If(_, _, Some(el)) = expr.kind {
             if let Some(rslt) = check_in_progress(el) {
                 return rslt;
             }
         }
 
-        if let hir::ExprKind::Match(_, arms, _) = &expr.kind {
-            let mut iter = arms.iter().filter_map(|arm| check_in_progress(&arm.body));
+        if let hir::ExprKind::Match(_, arms, _) = expr.kind {
+            let mut iter = arms.iter().filter_map(|arm| check_in_progress(arm.body));
             if let Some(span) = iter.next() {
                 if iter.next().is_none() {
                     return span;
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5ec79c586dc..545f432def5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1840,11 +1840,11 @@ impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
 impl Clean<Item> for ty::VariantDef {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
         let kind = match self.ctor_kind {
-            CtorKind::Const => VariantKind::CLike,
-            CtorKind::Fn => VariantKind::Tuple(
+            CtorKind::Const => Variant::CLike,
+            CtorKind::Fn => Variant::Tuple(
                 self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
             ),
-            CtorKind::Fictive => VariantKind::Struct(VariantStruct {
+            CtorKind::Fictive => Variant::Struct(VariantStruct {
                 struct_type: doctree::Plain,
                 fields_stripped: false,
                 fields: self
@@ -1861,25 +1861,21 @@ impl Clean<Item> for ty::VariantDef {
                     .collect(),
             }),
         };
-        let what_rustc_thinks = Item::from_def_id_and_parts(
-            self.def_id,
-            Some(self.ident.name),
-            VariantItem(Variant { kind }),
-            cx,
-        );
+        let what_rustc_thinks =
+            Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), VariantItem(kind), cx);
         // don't show `pub` for fields, which are always public
         Item { visibility: Inherited, ..what_rustc_thinks }
     }
 }
 
-impl Clean<VariantKind> for hir::VariantData<'_> {
-    fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
+impl Clean<Variant> for hir::VariantData<'_> {
+    fn clean(&self, cx: &DocContext<'_>) -> Variant {
         match self {
-            hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
+            hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
             hir::VariantData::Tuple(..) => {
-                VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
+                Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
             }
-            hir::VariantData::Unit(..) => VariantKind::CLike,
+            hir::VariantData::Unit(..) => Variant::CLike,
         }
     }
 }
@@ -2048,7 +2044,7 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
 
 impl Clean<Item> for hir::Variant<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
-        let kind = VariantItem(Variant { kind: self.data.clean(cx) });
+        let kind = VariantItem(self.data.clean(cx));
         let what_rustc_thinks =
             Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
         // don't show `pub` for variants, which are always public
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1f63fe5b957..666b11b5f80 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -237,9 +237,7 @@ impl Item {
         match *self.kind {
             StructItem(ref _struct) => Some(_struct.fields_stripped),
             UnionItem(ref union) => Some(union.fields_stripped),
-            VariantItem(Variant { kind: VariantKind::Struct(ref vstruct) }) => {
-                Some(vstruct.fields_stripped)
-            }
+            VariantItem(Variant::Struct(ref vstruct)) => Some(vstruct.fields_stripped),
             _ => None,
         }
     }
@@ -353,7 +351,7 @@ impl ItemKind {
         match self {
             StructItem(s) => s.fields.iter(),
             UnionItem(u) => u.fields.iter(),
-            VariantItem(Variant { kind: VariantKind::Struct(v) }) => v.fields.iter(),
+            VariantItem(Variant::Struct(v)) => v.fields.iter(),
             EnumItem(e) => e.variants.iter(),
             TraitItem(t) => t.items.iter(),
             ImplItem(i) => i.items.iter(),
@@ -1719,12 +1717,7 @@ crate struct Enum {
 }
 
 #[derive(Clone, Debug)]
-crate struct Variant {
-    crate kind: VariantKind,
-}
-
-#[derive(Clone, Debug)]
-crate enum VariantKind {
+crate enum Variant {
     CLike,
     Tuple(Vec<Type>),
     Struct(VariantStruct),
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 4d45c8866a7..b2773a29e29 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -55,13 +55,13 @@ crate trait DocFolder: Sized {
             }
             VariantItem(i) => {
                 let i2 = i.clone(); // this clone is small
-                match i.kind {
-                    VariantKind::Struct(mut j) => {
+                match i {
+                    Variant::Struct(mut j) => {
                         let num_fields = j.fields.len();
                         j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
                         j.fields_stripped |= num_fields != j.fields.len()
                             || j.fields.iter().any(|f| f.is_stripped());
-                        VariantItem(Variant { kind: VariantKind::Struct(j) })
+                        VariantItem(Variant::Struct(j))
                     }
                     _ => VariantItem(i2),
                 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 6a32be60991..2db89e8a7ca 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -3200,9 +3200,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 write!(w, "    ");
                 let name = v.name.as_ref().unwrap();
                 match *v.kind {
-                    clean::VariantItem(ref var) => match var.kind {
-                        clean::VariantKind::CLike => write!(w, "{}", name),
-                        clean::VariantKind::Tuple(ref tys) => {
+                    clean::VariantItem(ref var) => match var {
+                        clean::Variant::CLike => write!(w, "{}", name),
+                        clean::Variant::Tuple(ref tys) => {
                             write!(w, "{}(", name);
                             for (i, ty) in tys.iter().enumerate() {
                                 if i > 0 {
@@ -3212,7 +3212,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                             }
                             write!(w, ")");
                         }
-                        clean::VariantKind::Struct(ref s) => {
+                        clean::Variant::Struct(ref s) => {
                             render_struct(w, v, None, s.struct_type, &s.fields, "    ", false, cx);
                         }
                     },
@@ -3249,25 +3249,22 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 id = id,
                 name = variant.name.as_ref().unwrap()
             );
-            if let clean::VariantItem(ref var) = *variant.kind {
-                if let clean::VariantKind::Tuple(ref tys) = var.kind {
-                    write!(w, "(");
-                    for (i, ty) in tys.iter().enumerate() {
-                        if i > 0 {
-                            write!(w, ",&nbsp;");
-                        }
-                        write!(w, "{}", ty.print());
+            if let clean::VariantItem(clean::Variant::Tuple(ref tys)) = *variant.kind {
+                write!(w, "(");
+                for (i, ty) in tys.iter().enumerate() {
+                    if i > 0 {
+                        write!(w, ",&nbsp;");
                     }
-                    write!(w, ")");
+                    write!(w, "{}", ty.print());
                 }
+                write!(w, ")");
             }
             write!(w, "</code></div>");
             document(w, cx, variant, Some(it));
             document_non_exhaustive(w, variant);
 
-            use crate::clean::{Variant, VariantKind};
-            if let clean::VariantItem(Variant { kind: VariantKind::Struct(ref s) }) = *variant.kind
-            {
+            use crate::clean::Variant;
+            if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
                 let variant_id = cx.derive_id(format!(
                     "{}.{}.fields",
                     ItemType::Variant,
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index ec8024ffca5..3ffb72ba3ee 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -648,8 +648,7 @@ function defocusSearchBar() {
          */
         function execQuery(query, searchWords, filterCrates) {
             function itemTypeFromName(typename) {
-                var length = itemTypes.length;
-                for (var i = 0; i < length; ++i) {
+                for (var i = 0, len = itemTypes.length; i < len; ++i) {
                     if (itemTypes[i] === typename) {
                         return i;
                     }
@@ -667,8 +666,7 @@ function defocusSearchBar() {
 
             function transformResults(results, isType) {
                 var out = [];
-                var length = results.length;
-                for (var i = 0; i < length; ++i) {
+                for (var i = 0, len = results.length; i < len; ++i) {
                     if (results[i].id > -1) {
                         var obj = searchIndex[results[i].id];
                         obj.lev = results[i].lev;
@@ -697,11 +695,11 @@ function defocusSearchBar() {
                     }
                 }
                 results = ar;
-                var i;
-                var nresults = results.length;
-                for (i = 0; i < nresults; ++i) {
-                    results[i].word = searchWords[results[i].id];
-                    results[i].item = searchIndex[results[i].id] || {};
+                var i, len, result;
+                for (i = 0, len = results.length; i < len; ++i) {
+                    result = results[i];
+                    result.word = searchWords[result.id];
+                    result.item = searchIndex[result.id] || {};
                 }
                 // if there are no results then return to default and fail
                 if (results.length === 0) {
@@ -775,8 +773,7 @@ function defocusSearchBar() {
                     return 0;
                 });
 
-                var length = results.length;
-                for (i = 0; i < length; ++i) {
+                for (i = 0, len = results.length; i < len; ++i) {
                     var result = results[i];
 
                     // this validation does not make sense when searching by types
@@ -833,11 +830,10 @@ function defocusSearchBar() {
                         var vlength = val.generics.length;
                         for (var y = 0; y < vlength; ++y) {
                             var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
-                            var elength = elems.length;
                             var firstGeneric = getObjectFromId(val.generics[y]).name;
-                            for (var x = 0; x < elength; ++x) {
+                            for (var x = 0, elength = elems.length; x < elength; ++x) {
                                 var tmp_lev = levenshtein(getObjectFromId(elems[x]).name,
-                                                          firstGeneric);
+                                                                          firstGeneric);
                                 if (tmp_lev < lev.lev) {
                                     lev.lev = tmp_lev;
                                     lev.pos = x;
@@ -861,7 +857,7 @@ function defocusSearchBar() {
             // Check for type name and type generics (if any).
             function checkType(obj, val, literalSearch) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
-                var x;
+                var len, x, y, e_len, firstGeneric;
                 if (obj[NAME] === val.name) {
                     if (literalSearch === true) {
                         if (val.generics && val.generics.length !== 0) {
@@ -870,10 +866,12 @@ function defocusSearchBar() {
                                 var elems = obj[GENERICS_DATA].slice(0);
                                 var allFound = true;
 
-                                for (var y = 0; allFound === true && y < val.generics.length; ++y) {
+                                len = val.generics.length;
+                                for (y = 0; allFound === true && y < len; ++y) {
                                     allFound = false;
-                                    var firstGeneric = getObjectFromId(val.generics[y]).name;
-                                    for (x = 0; allFound === false && x < elems.length; ++x) {
+                                    firstGeneric = getObjectFromId(val.generics[y]).name;
+                                    e_len = elems.length;
+                                    for (x = 0; allFound === false && x < e_len; ++x) {
                                         allFound = getObjectFromId(elems[x]).name === firstGeneric;
                                     }
                                     if (allFound === true) {
@@ -903,12 +901,10 @@ function defocusSearchBar() {
                 // Names didn't match so let's check if one of the generic types could.
                 if (literalSearch === true) {
                      if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
-                        var length = obj[GENERICS_DATA].length;
-                        for (x = 0; x < length; ++x) {
-                            if (obj[GENERICS_DATA][x] === val.name) {
-                                return true;
-                            }
-                        }
+                        return obj[GENERICS_DATA].some(
+                            function(name) {
+                                return name === val.name;
+                            });
                     }
                     return false;
                 }
@@ -965,7 +961,7 @@ function defocusSearchBar() {
                     if (typeof ret[0] === "string") {
                         ret = [ret];
                     }
-                    for (var x = 0; x < ret.length; ++x) {
+                    for (var x = 0, len = ret.length; x < len; ++x) {
                         var tmp = ret[x];
                         if (typePassesFilter(typeFilter, tmp[1]) === false) {
                             continue;
@@ -1072,23 +1068,22 @@ function defocusSearchBar() {
                 // aliases to be before the others in the displayed results.
                 var aliases = [];
                 var crateAliases = [];
-                var i;
                 if (filterCrates !== undefined) {
                     if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
-                        for (i = 0; i < ALIASES[filterCrates][query.search].length; ++i) {
-                            aliases.push(
-                                createAliasFromItem(
-                                    searchIndex[ALIASES[filterCrates][query.search][i]]));
+                        var query_aliases = ALIASES[filterCrates][query.search];
+                        var len = query_aliases.length;
+                        for (var i = 0; i < len; ++i) {
+                            aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
                         }
                     }
                 } else {
                     Object.keys(ALIASES).forEach(function(crate) {
                         if (ALIASES[crate][query.search]) {
                             var pushTo = crate === window.currentCrate ? crateAliases : aliases;
-                            for (i = 0; i < ALIASES[crate][query.search].length; ++i) {
-                                pushTo.push(
-                                    createAliasFromItem(
-                                        searchIndex[ALIASES[crate][query.search][i]]));
+                            var query_aliases = ALIASES[crate][query.search];
+                            var len = query_aliases.length;
+                            for (var i = 0; i < len; ++i) {
+                                pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
                             }
                         }
                     });
@@ -1123,11 +1118,12 @@ function defocusSearchBar() {
 
             // quoted values mean literal search
             var nSearchWords = searchWords.length;
-            var i;
+            var i, it;
             var ty;
             var fullId;
             var returned;
             var in_args;
+            var len;
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
@@ -1175,7 +1171,7 @@ function defocusSearchBar() {
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 var inputs = input.split(",").map(trimmer).sort();
-                for (i = 0; i < inputs.length; ++i) {
+                for (i = 0, len = inputs.length; i < len; ++i) {
                     inputs[i] = extractGenerics(inputs[i]);
                 }
                 var output = extractGenerics(parts[1]);
@@ -1200,7 +1196,7 @@ function defocusSearchBar() {
                             is_module = true;
                         } else {
                             var allFound = true;
-                            for (var it = 0; allFound === true && it < inputs.length; it++) {
+                            for (it = 0, len = inputs.length; allFound === true && it < len; it++) {
                                 allFound = checkType(type, inputs[it], true);
                             }
                             in_args = allFound;
@@ -1243,7 +1239,7 @@ function defocusSearchBar() {
 
                 var paths = valLower.split("::");
                 var j;
-                for (j = 0; j < paths.length; ++j) {
+                for (j = 0, len = paths.length; j < len; ++j) {
                     if (paths[j] === "") {
                         paths.splice(j, 1);
                         j -= 1;
@@ -1365,7 +1361,7 @@ function defocusSearchBar() {
          * @return {[boolean]}       [Whether the result is valid or not]
          */
         function validateResult(name, path, keys, parent) {
-            for (var i = 0; i < keys.length; ++i) {
+            for (var i = 0, len = keys.length; i < len; ++i) {
                 // each check is for validation so we negate the conditions and invalidate
                 if (!(
                     // check for an exact name match
@@ -1686,7 +1682,7 @@ function defocusSearchBar() {
             function getSmallest(arrays, positions, notDuplicates) {
                 var start = null;
 
-                for (var it = 0; it < positions.length; ++it) {
+                for (var it = 0, len = positions.length; it < len; ++it) {
                     if (arrays[it].length > positions[it] &&
                         (start === null || start > arrays[it][positions[it]].lev) &&
                         !notDuplicates[arrays[it][positions[it]].fullPath]) {
@@ -1701,7 +1697,7 @@ function defocusSearchBar() {
                 var positions = [];
                 var notDuplicates = {};
 
-                for (var x = 0; x < arrays.length; ++x) {
+                for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
                     positions.push(0);
                 }
                 while (ret.length < MAX_RESULTS) {
@@ -1710,7 +1706,7 @@ function defocusSearchBar() {
                     if (smallest === null) {
                         break;
                     }
-                    for (x = 0; x < arrays.length && ret.length < MAX_RESULTS; ++x) {
+                    for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
                         if (arrays[x].length > positions[x] &&
                                 arrays[x][positions[x]].lev === smallest &&
                                 !notDuplicates[arrays[x][positions[x]].fullPath]) {
@@ -1730,7 +1726,7 @@ function defocusSearchBar() {
                 "others": [],
             };
 
-            for (var i = 0; i < queries.length; ++i) {
+            for (var i = 0, len = queries.length; i < len; ++i) {
                 query = queries[i].trim();
                 if (query.length !== 0) {
                     var tmp = execQuery(getQuery(query), searchWords, filterCrates);
@@ -1884,7 +1880,7 @@ function defocusSearchBar() {
                             ALIASES[crate][alias_name] = [];
                         }
                         local_aliases = aliases[alias_name];
-                        for (j = 0; j < local_aliases.length; ++j) {
+                        for (j = 0, len = local_aliases.length; j < len; ++j) {
                             ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
                         }
                     }
@@ -2052,8 +2048,7 @@ function defocusSearchBar() {
             div.appendChild(h3);
             var ul = document.createElement("ul");
 
-            var length = filtered.length;
-            for (var i = 0; i < length; ++i) {
+            for (var i = 0, len = filtered.length; i < len; ++i) {
                 var item = filtered[i];
                 var name = item[0];
                 var desc = item[1]; // can be null
@@ -2122,21 +2117,18 @@ function defocusSearchBar() {
         }
 
         var libs = Object.getOwnPropertyNames(imp);
-        var llength = libs.length;
-        for (var i = 0; i < llength; ++i) {
+        for (var i = 0, llength = libs.length; i < llength; ++i) {
             if (libs[i] === currentCrate) { continue; }
             var structs = imp[libs[i]];
 
-            var slength = structs.length;
             struct_loop:
-            for (var j = 0; j < slength; ++j) {
+            for (var j = 0, slength = structs.length; j < slength; ++j) {
                 var struct = structs[j];
 
                 var list = struct.synthetic ? synthetic_implementors : implementors;
 
                 if (struct.synthetic) {
-                    var stlength = struct.types.length;
-                    for (var k = 0; k < stlength; k++) {
+                    for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
                         if (inlined_types.has(struct.types[k])) {
                             continue struct_loop;
                         }
@@ -2853,7 +2845,7 @@ function defocusSearchBar() {
             return 0;
         });
         var savedCrate = getSettingValue("saved-filter-crate");
-        for (var i = 0; i < crates_text.length; ++i) {
+        for (var i = 0, len = crates_text.length; i < len; ++i) {
             var option = document.createElement("option");
             option.value = crates_text[i];
             option.innerText = crates_text[i];
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 6805f2a266f..a9cc0ffdf79 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -8,7 +8,7 @@ function getCurrentFilePath() {
     var parts = window.location.pathname.split("/");
     var rootPathParts = window.rootPath.split("/");
 
-    for (var i = 0; i < rootPathParts.length; ++i) {
+    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
         if (rootPathParts[i] === "..") {
             parts.pop();
         }
@@ -35,12 +35,14 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
     };
     name.innerText = elem["name"];
 
+    var i, len;
+
     var children = document.createElement("div");
     children.className = "children";
     var folders = document.createElement("div");
     folders.className = "folders";
     if (elem.dirs) {
-        for (var i = 0; i < elem.dirs.length; ++i) {
+        for (i = 0, len = elem.dirs.length; i < len; ++i) {
             if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
                                hasFoundFile) === true) {
                 addClass(name, "expand");
@@ -53,7 +55,7 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
     var files = document.createElement("div");
     files.className = "files";
     if (elem.files) {
-        for (i = 0; i < elem.files.length; ++i) {
+        for (i = 0, len = elem.files.length; i < len; ++i) {
             var file = document.createElement("a");
             file.innerText = elem.files[i];
             file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 5dea64ef145..7d05cb016b6 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -482,8 +482,8 @@ impl From<clean::VariantStruct> for Struct {
 
 impl From<clean::Variant> for Variant {
     fn from(variant: clean::Variant) -> Self {
-        use clean::VariantKind::*;
-        match variant.kind {
+        use clean::Variant::*;
+        match variant {
             CLike => Variant::Plain,
             Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()),
             Struct(s) => Variant::Struct(ids(s.fields)),
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index a1924422f0e..162b70973b4 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -94,7 +94,7 @@ impl<'a> DocFolder for Stripper<'a> {
             // implementations of traits are always public.
             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
             // Struct variant fields have inherited visibility
-            clean::VariantItem(clean::Variant { kind: clean::VariantKind::Struct(..) }) => true,
+            clean::VariantItem(clean::Variant::Struct(..)) => true,
             _ => false,
         };
 
diff --git a/src/test/codegen/issue-59352.rs b/src/test/codegen/issue-59352.rs
new file mode 100644
index 00000000000..28bb8591232
--- /dev/null
+++ b/src/test/codegen/issue-59352.rs
@@ -0,0 +1,18 @@
+// This test is a mirror of mir-opt/issues/issue-59352.rs. The LLVM inliner doesn't inline
+// `char::method::is_digit()` and `char::method::to_digit()`, probably because of their size.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, mir-opt/issues/issue-59352.rs will need to be updated and this
+// test case should be removed as it will become redundant.
+
+// mir-opt-level=2 enables inlining and enables LLVM to optimize away the unreachable panic call.
+// compile-flags: -O -Z mir-opt-level=2
+
+#![crate_type = "rlib"]
+
+// CHECK-LABEL: @num_to_digit
+#[no_mangle]
+pub fn num_to_digit(num: char) -> u32 {
+    // CHECK-NOT: panic
+    if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
diff --git a/src/test/mir-opt/issues/issue-59352.rs b/src/test/mir-opt/issues/issue-59352.rs
new file mode 100644
index 00000000000..9e59337a01d
--- /dev/null
+++ b/src/test/mir-opt/issues/issue-59352.rs
@@ -0,0 +1,19 @@
+// This test is a mirror of codegen/issue-59352.rs.
+// The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
+// as effectively `if x.is_some() { x.unwrap() } else { 0 }`.
+//
+// Currently, the MIR optimizer isn't capable of removing the unreachable panic in this test case.
+// Once the optimizer can do that, this test case will need to be updated and codegen/issue-59352.rs
+// removed.
+
+// EMIT_MIR issue_59352.num_to_digit.PreCodegen.after.mir
+// compile-flags: -Z mir-opt-level=2 -Z span_free_formats
+
+pub fn num_to_digit(num: char) -> u32 {
+    // CHECK-NOT: panic
+    if num.is_digit(8) { num.to_digit(8).unwrap() } else { 0 }
+}
+
+pub fn main() {
+    num_to_digit('2');
+}
diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
new file mode 100644
index 00000000000..04a8c94e003
--- /dev/null
+++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -0,0 +1,102 @@
+// MIR for `num_to_digit` after PreCodegen
+
+fn num_to_digit(_1: char) -> u32 {
+    debug num => _1;                     // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
+    let mut _2: bool;                    // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+    let mut _4: char;                    // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+    let mut _5: u32;                     // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    let mut _10: isize;                  // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+    scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
+        debug self => _8;                // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        debug radix => _5;               // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let mut _6: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let _7: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        let mut _8: char;                // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
+            debug self => _6;            // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        }
+    }
+    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
+        debug self => _3;                // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        let mut _9: isize;               // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        scope 4 {
+            debug val => _0;             // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        _8 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
+        StorageLive(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        _5 = const 8_u32;                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageLive(_6);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageLive(_7);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        _7 = char::methods::<impl char>::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:8: 14:23
+                                         // + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1: {
+        StorageLive(_3);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+        StorageLive(_4);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+        _4 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
+        _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:30: 14:38
+                                         // + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb2: {
+        _0 = const 0_u32;                // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
+        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+
+    bb3: {
+        StorageDead(_4);                 // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
+        StorageLive(_9);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
+        _9 = discriminant(_3);           // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        switchInt(move _9) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+    }
+
+    bb4: {
+        StorageDead(_2);                 // scope 0 at $DIR/issue-59352.rs:14:62: 14:63
+        return;                          // scope 0 at $DIR/issue-59352.rs:15:2: 15:2
+    }
+
+    bb5: {
+        _6 = &_7;                        // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        _10 = discriminant((*_6));       // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        _2 = Eq(_10, const 1_isize);     // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_6);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_7);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
+        StorageDead(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+
+    bb6: {
+        core::panicking::panic(const "called `Option::unwrap()` on a `None` value"); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:26: 14:50
+                                         // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar(<ZST>)) }
+                                         // ty::Const
+                                         // + ty: &str
+                                         // + val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, size: Size { raw: 43 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 })
+                                         // mir::Constant
+                                         // + span: $DIR/issue-59352.rs:14:26: 14:50
+                                         // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, size: Size { raw: 43 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) }
+    }
+
+    bb7: {
+        unreachable;                     // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+    }
+
+    bb8: {
+        _0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
+        StorageDead(_9);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
+        StorageDead(_3);                 // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
+        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+}
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 8e17f291908..26a66fb021e 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -10,6 +10,6 @@ clap = "2.25.0"
 env_logger = "0.7.1"
 
 [dependencies.mdbook]
-version = "0.4.5"
+version = "0.4.6"
 default-features = false
 features = ["search"]