diff --git a/Cargo.lock b/Cargo.lock index 94fb49fd43ea2..5e5a48ad5258b 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 52350c5d07844..07e637b88f9c0 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 4afa6689b92c7..6177e39ba9e4c 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 5ec79c586dcac..545f432def5a7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1840,11 +1840,11 @@ impl Clean for rustc_hir::VariantData<'_> { impl Clean 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 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 for hir::VariantData<'_> { - fn clean(&self, cx: &DocContext<'_>) -> VariantKind { +impl Clean 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> for (&hir::Item<'_>, Option) { impl Clean 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 1f63fe5b95708..666b11b5f806d 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), Struct(VariantStruct), diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 4d45c8866a793..b2773a29e2905 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 6a32be609911a..2db89e8a7ca68 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, ", "); - } - 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, ", "); } - write!(w, ")"); + write!(w, "{}", ty.print()); } + write!(w, ")"); } write!(w, ""); 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 ec8024ffca529..3ffb72ba3ee8b 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 6805f2a266f09..a9cc0ffdf79b0 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 5dea64ef14587..7d05cb016b67c 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -482,8 +482,8 @@ impl From for Struct { impl From 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 a1924422f0e5e..162b70973b418 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 0000000000000..28bb85912324e --- /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 0000000000000..9e59337a01d5c --- /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 0000000000000..04a8c94e003c4 --- /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; // 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::::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; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + let _7: std::option::Option; // 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::::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::::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::::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 {std::char::methods::::to_digit}, val: Value(Scalar()) } + } + + 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::::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 {std::char::methods::::to_digit}, val: Value(Scalar()) } + } + + 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()) } + // 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 8e17f2919082b..26a66fb021e4d 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"]