diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index fd29053433e5..7b1660b501bf 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -922,7 +922,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { } } -/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)" +/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" pub fn version_str() -> Option<&'static str> { option_env!("CFG_VERSION") } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d32180525bf7..bd142677cf9e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -44,6 +44,7 @@ struct MarkSymbolVisitor<'tcx> { repr_has_repr_c: bool, in_pat: bool, inherited_pub_visibility: bool, + pub_visibility: bool, ignore_variant_stack: Vec, // maps from tuple struct constructors to tuple struct items struct_constructors: FxHashMap, @@ -188,27 +189,33 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn visit_node(&mut self, node: Node<'tcx>) { let had_repr_c = self.repr_has_repr_c; - self.repr_has_repr_c = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; + let had_pub_visibility = self.pub_visibility; + self.repr_has_repr_c = false; self.inherited_pub_visibility = false; + self.pub_visibility = false; match node { - Node::Item(item) => match item.kind { - hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id); - self.repr_has_repr_c = def.repr.c(); + Node::Item(item) => { + self.pub_visibility = item.vis.node.is_pub(); - intravisit::walk_item(self, &item); - } - hir::ItemKind::Enum(..) => { - self.inherited_pub_visibility = item.vis.node.is_pub(); + match item.kind { + hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { + let def = self.tcx.adt_def(item.def_id); + self.repr_has_repr_c = def.repr.c(); - intravisit::walk_item(self, &item); - } - hir::ItemKind::ForeignMod { .. } => {} - _ => { - intravisit::walk_item(self, &item); + intravisit::walk_item(self, &item); + } + hir::ItemKind::Enum(..) => { + self.inherited_pub_visibility = self.pub_visibility; + + intravisit::walk_item(self, &item); + } + hir::ItemKind::ForeignMod { .. } => {} + _ => { + intravisit::walk_item(self, &item); + } } - }, + } Node::TraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } @@ -220,8 +227,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } _ => {} } - self.repr_has_repr_c = had_repr_c; + self.pub_visibility = had_pub_visibility; self.inherited_pub_visibility = had_inherited_pub_visibility; + self.repr_has_repr_c = had_repr_c; } fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::ExprField<'_>]) { @@ -259,10 +267,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { ) { let has_repr_c = self.repr_has_repr_c; let inherited_pub_visibility = self.inherited_pub_visibility; - let live_fields = def - .fields() - .iter() - .filter(|f| has_repr_c || inherited_pub_visibility || f.vis.node.is_pub()); + let pub_visibility = self.pub_visibility; + let live_fields = def.fields().iter().filter(|f| { + has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub())) + }); self.live_symbols.extend(live_fields.map(|f| f.hir_id)); intravisit::walk_struct_def(self, def); @@ -500,6 +508,7 @@ fn find_live<'tcx>( repr_has_repr_c: false, in_pat: false, inherited_pub_visibility: false, + pub_visibility: false, ignore_variant_stack: vec![], struct_constructors, }; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 95dd54976b2c..065acd3f38bb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -192,14 +192,26 @@ impl str { #[stable(feature = "is_char_boundary", since = "1.9.0")] #[inline] pub fn is_char_boundary(&self, index: usize) -> bool { - // 0 and len are always ok. + // 0 is always ok. // Test for 0 explicitly so that it can optimize out the check // easily and skip reading string data for that case. - if index == 0 || index == self.len() { + // Note that optimizing `self.get(..index)` relies on this. + if index == 0 { return true; } + match self.as_bytes().get(index) { - None => false, + // For `None` we have two options: + // + // - index == self.len() + // Empty strings are valid, so return true + // - index > self.len() + // In this case return false + // + // The check is placed exactly here, because it improves generated + // code on higher opt-levels. See PR #84751 for more details. + None => index == self.len(), + // This is bit magic equivalent to: b < 128 || b >= 192 Some(&b) => (b as i8) >= -0x40, } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 326a6fdaa80f..f9972ac7b9d9 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -451,6 +451,22 @@ impl Step for Std { builder.run(&mut cargo.into()); }; + + let paths = builder + .paths + .iter() + .map(components_simplified) + .filter_map(|path| { + if path.get(0) == Some(&"library") { + Some(path[1].to_owned()) + } else if !path.is_empty() { + Some(path[0].to_owned()) + } else { + None + } + }) + .collect::>(); + // Only build the following crates. While we could just iterate over the // folder structure, that would also build internal crates that we do // not want to show in documentation. These crates will later be visited @@ -464,20 +480,17 @@ impl Step for Std { let krates = ["core", "alloc", "std", "proc_macro", "test"]; for krate in &krates { run_cargo_rustdoc_for(krate); + if paths.iter().any(|p| p == krate) { + // No need to document more of the libraries if we have the one we want. + break; + } } builder.cp_r(&out_dir, &out); // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. - for path in builder.paths.iter().map(components_simplified) { - let requested_crate = if path.get(0) == Some(&"library") { - &path[1] - } else if !path.is_empty() { - &path[0] - } else { - continue; - }; - if krates.contains(&requested_crate) { + for requested_crate in paths { + if krates.iter().any(|k| *k == requested_crate.as_str()) { let index = out.join(requested_crate).join("index.html"); open(builder, &index); } diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index a9398649cf05..fd6dc563a0ec 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -34,7 +34,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py build --stage 0 src/tools/build-manifest && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 2 src/tools/tidy && \ - python3 ../x.py doc --stage 0 library/std && \ + python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ # Runs checks to ensure that there are no ES5 issues in our JS code. es-check es5 ../src/librustdoc/html/static/*.js diff --git a/src/test/ui/cast/issue-84213.fixed b/src/test/ui/cast/issue-84213.fixed index e1a60557a20c..b5c4a7752966 100644 --- a/src/test/ui/cast/issue-84213.fixed +++ b/src/test/ui/cast/issue-84213.fixed @@ -6,6 +6,7 @@ struct Something { fn main() { let mut something = Something { field: 1337 }; + let _ = something.field; let _pointer_to_something = &something as *const Something; //~^ ERROR: non-primitive cast diff --git a/src/test/ui/cast/issue-84213.rs b/src/test/ui/cast/issue-84213.rs index 3df264bdffb6..6eb81291abc7 100644 --- a/src/test/ui/cast/issue-84213.rs +++ b/src/test/ui/cast/issue-84213.rs @@ -6,6 +6,7 @@ struct Something { fn main() { let mut something = Something { field: 1337 }; + let _ = something.field; let _pointer_to_something = something as *const Something; //~^ ERROR: non-primitive cast diff --git a/src/test/ui/cast/issue-84213.stderr b/src/test/ui/cast/issue-84213.stderr index a76aac580131..1b71d4db511b 100644 --- a/src/test/ui/cast/issue-84213.stderr +++ b/src/test/ui/cast/issue-84213.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `Something` as `*const Something` - --> $DIR/issue-84213.rs:10:33 + --> $DIR/issue-84213.rs:11:33 | LL | let _pointer_to_something = something as *const Something; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast @@ -10,7 +10,7 @@ LL | let _pointer_to_something = &something as *const Something; | ^ error[E0605]: non-primitive cast: `Something` as `*mut Something` - --> $DIR/issue-84213.rs:13:37 + --> $DIR/issue-84213.rs:14:37 | LL | let _mut_pointer_to_something = something as *mut Something; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast diff --git a/src/test/ui/lint/dead-code/issue-85255.rs b/src/test/ui/lint/dead-code/issue-85255.rs new file mode 100644 index 000000000000..9a4d9fbad35b --- /dev/null +++ b/src/test/ui/lint/dead-code/issue-85255.rs @@ -0,0 +1,22 @@ +// Unused `pub` fields in non-`pub` structs should also trigger dead code warnings. +// check-pass + +#![warn(dead_code)] + +struct Foo { + a: i32, //~ WARNING: field is never read + pub b: i32, //~ WARNING: field is never read +} + +struct Bar; + +impl Bar { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function is never used +} + + +fn main() { + let _ = Foo { a: 1, b: 2 }; + let _ = Bar; +} diff --git a/src/test/ui/lint/dead-code/issue-85255.stderr b/src/test/ui/lint/dead-code/issue-85255.stderr new file mode 100644 index 000000000000..736464392953 --- /dev/null +++ b/src/test/ui/lint/dead-code/issue-85255.stderr @@ -0,0 +1,32 @@ +warning: field is never read: `a` + --> $DIR/issue-85255.rs:7:5 + | +LL | a: i32, + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-85255.rs:4:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: field is never read: `b` + --> $DIR/issue-85255.rs:8:5 + | +LL | pub b: i32, + | ^^^^^^^^^^ + +warning: associated function is never used: `a` + --> $DIR/issue-85255.rs:14:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function is never used: `b` + --> $DIR/issue-85255.rs:15:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: 4 warnings emitted +