diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86f60349c6777..8c4d7bde2df04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -575,6 +575,7 @@ jobs: CACHE_DOMAIN: ci-caches-gha.rust-lang.org if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" strategy: + fast-fail: false matrix: include: - name: aarch64-gnu diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index b767d9ebed723..c401a47432eb4 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -819,13 +819,13 @@ impl Handle, mar } } -impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { +impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::Edge> { + /// Helps implementations of `insert_fit` for a particular `NodeType`, + /// by taking care of leaf data. /// Inserts a new key/value pair between the key/value pairs to the right and left of /// this edge. This method assumes that there is enough space in the node for the new /// pair to fit. - /// - /// The returned pointer points to the inserted value. - fn insert_fit(&mut self, key: K, val: V) -> *mut V { + fn leafy_insert_fit(&mut self, key: K, val: V) { // Necessary for correctness, but in a private module debug_assert!(self.node.len() < CAPACITY); @@ -834,11 +834,23 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge slice_insert(self.node.vals_mut(), self.idx, val); (*self.node.as_leaf_mut()).len += 1; - - self.node.vals_mut().get_unchecked_mut(self.idx) } } +} +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key/value pair between the key/value pairs to the right and left of + /// this edge. This method assumes that there is enough space in the node for the new + /// pair to fit. + /// + /// The returned pointer points to the inserted value. + fn insert_fit(&mut self, key: K, val: V) -> *mut V { + self.leafy_insert_fit(key, val); + unsafe { self.node.vals_mut().get_unchecked_mut(self.idx) } + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { /// Inserts a new key/value pair between the key/value pairs to the right and left of /// this edge. This method splits the node if there isn't enough room. /// @@ -880,14 +892,6 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: } } - /// Unsafely asserts to the compiler some static information about whether the underlying - /// node of this handle is a `Leaf` or an `Internal`. - unsafe fn cast_unchecked( - &mut self, - ) -> Handle, K, V, NewType>, marker::Edge> { - unsafe { Handle::new_edge(self.node.cast_unchecked(), self.idx) } - } - /// Inserts a new key/value pair and an edge that will go to the right of that new pair /// between this edge and the key/value pair to the right of this edge. This method assumes /// that there is enough space in the node for the new pair to fit. @@ -897,8 +901,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: debug_assert!(edge.height == self.node.height - 1); unsafe { - // This cast is a lie, but it allows us to reuse the key/value insertion logic. - self.cast_unchecked::().insert_fit(key, val); + self.leafy_insert_fit(key, val); slice_insert( slice::from_raw_parts_mut( @@ -994,18 +997,11 @@ impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker } } -impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> { - /// Splits the underlying node into three parts: - /// - /// - The node is truncated to only contain the key/value pairs to the right of - /// this handle. - /// - The key and value pointed to by this handle and extracted. - /// - All the key/value pairs to the right of this handle are put into a newly - /// allocated node. - pub fn split(mut self) -> (NodeRef, K, V, marker::Leaf>, K, V, Root) { +impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::KV> { + /// Helps implementations of `split` for a particular `NodeType`, + /// by taking care of leaf data. + fn leafy_split(&mut self, new_node: &mut LeafNode) -> (K, V, usize) { unsafe { - let mut new_node = Box::new(LeafNode::new()); - let k = ptr::read(self.node.keys().get_unchecked(self.idx)); let v = ptr::read(self.node.vals().get_unchecked(self.idx)); @@ -1024,6 +1020,24 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> (*self.node.as_leaf_mut()).len = self.idx as u16; new_node.len = new_len as u16; + (k, v, new_len) + } + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> { + /// Splits the underlying node into three parts: + /// + /// - The node is truncated to only contain the key/value pairs to the right of + /// this handle. + /// - The key and value pointed to by this handle and extracted. + /// - All the key/value pairs to the right of this handle are put into a newly + /// allocated node. + pub fn split(mut self) -> (NodeRef, K, V, marker::Leaf>, K, V, Root) { + unsafe { + let mut new_node = Box::new(LeafNode::new()); + + let (k, v, _) = self.leafy_split(&mut new_node); (self.node, k, v, Root { node: BoxedNode::from_leaf(new_node), height: 0 }) } @@ -1055,31 +1069,15 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: unsafe { let mut new_node = Box::new(InternalNode::new()); - let k = ptr::read(self.node.keys().get_unchecked(self.idx)); - let v = ptr::read(self.node.vals().get_unchecked(self.idx)); - + let (k, v, new_len) = self.leafy_split(&mut new_node.data); let height = self.node.height; - let new_len = self.node.len() - self.idx - 1; - ptr::copy_nonoverlapping( - self.node.keys().as_ptr().add(self.idx + 1), - new_node.data.keys.as_mut_ptr() as *mut K, - new_len, - ); - ptr::copy_nonoverlapping( - self.node.vals().as_ptr().add(self.idx + 1), - new_node.data.vals.as_mut_ptr() as *mut V, - new_len, - ); ptr::copy_nonoverlapping( self.node.as_internal().edges.as_ptr().add(self.idx + 1), new_node.edges.as_mut_ptr(), new_len + 1, ); - (*self.node.as_leaf_mut()).len = self.idx as u16; - new_node.data.len = new_len as u16; - let mut new_root = Root { node: BoxedNode::from_internal(new_node), height }; for i in 0..(new_len + 1) { diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 048c9c5ddaaee..eb50dc28b9f11 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1601,6 +1601,29 @@ $EndFeature, " } } + doc_comment! { + concat!("Computes the absolute value of `self` without any wrapping +or panicking. + + +# Examples + +Basic usage: + +``` +", $Feature, "#![feature(unsigned_abs)] +assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), "); +assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), "); +assert_eq!((-128i8).unsigned_abs(), 128u8);", +$EndFeature, " +```"), + #[unstable(feature = "unsigned_abs", issue = "74913")] + #[inline] + pub const fn unsigned_abs(self) -> $UnsignedT { + self.wrapping_abs() as $UnsignedT + } + } + doc_comment! { concat!("Wrapping (modular) exponentiation. Computes `self.pow(exp)`, wrapping around at the boundary of the type. diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index a64b43ca3ad45..6fdf635039f68 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -319,15 +319,7 @@ impl Ipv4Addr { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { - // FIXME: should just be u32::from_be_bytes([a, b, c, d]), - // once that method is no longer rustc_const_unstable - Ipv4Addr { - inner: c::in_addr { - s_addr: u32::to_be( - ((a as u32) << 24) | ((b as u32) << 16) | ((c as u32) << 8) | (d as u32), - ), - }, - } + Ipv4Addr { inner: c::in_addr { s_addr: u32::from_le_bytes([a, b, c, d]) } } } /// An IPv4 address with the address pointing to localhost: 127.0.0.1. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index a4a1d5193b9b9..98b6be29c073b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1355,7 +1355,7 @@ pub struct RustAnalyzer { } impl Step for RustAnalyzer { - type Output = PathBuf; + type Output = Option; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -1373,11 +1373,17 @@ impl Step for RustAnalyzer { }); } - fn run(self, builder: &Builder<'_>) -> PathBuf { + fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); + if target.contains("riscv64") { + // riscv64 currently has an LLVM bug that makes rust-analyzer unable + // to build. See #74813 for details. + return None; + } + let src = builder.src.join("src/tools/rust-analyzer"); let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer"); let name = pkgname(builder, "rust-analyzer"); @@ -1431,7 +1437,7 @@ impl Step for RustAnalyzer { builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target)); let _time = timeit(builder); builder.run(&mut cmd); - distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)) + Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))) } } @@ -1789,7 +1795,7 @@ impl Step for Extended { tarballs.push(rustc_installer); tarballs.push(cargo_installer); tarballs.extend(rls_installer.clone()); - tarballs.push(rust_analyzer_installer.clone()); + tarballs.extend(rust_analyzer_installer.clone()); tarballs.push(clippy_installer); tarballs.extend(miri_installer.clone()); tarballs.extend(rustfmt_installer.clone()); @@ -1867,7 +1873,9 @@ impl Step for Extended { if rls_installer.is_none() { contents = filter(&contents, "rls"); } - contents = filter(&contents, "rust-analyzer"); + if rust_analyzer_installer.is_none() { + contents = filter(&contents, "rust-analyzer"); + } if miri_installer.is_none() { contents = filter(&contents, "miri"); } @@ -1914,7 +1922,9 @@ impl Step for Extended { if rls_installer.is_some() { prepare("rls"); } - prepare("rust-analyzer"); + if rust_analyzer_installer.is_some() { + prepare("rust-analyzer"); + } if miri_installer.is_some() { prepare("miri"); } @@ -1976,7 +1986,9 @@ impl Step for Extended { if rls_installer.is_some() { prepare("rls"); } - prepare("rust-analyzer"); + if rust_analyzer_installer.is_some() { + prepare("rust-analyzer"); + } if miri_installer.is_some() { prepare("miri"); } @@ -2076,23 +2088,25 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); } - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-analyzer") - .args(&heat_flags) - .arg("-cg") - .arg("RustAnalyzerGroup") - .arg("-dr") - .arg("RustAnalyzer") - .arg("-var") - .arg("var.RustAnalyzerDir") - .arg("-out") - .arg(exe.join("RustAnalyzerGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); + if rust_analyzer_installer.is_some() { + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-analyzer") + .args(&heat_flags) + .arg("-cg") + .arg("RustAnalyzerGroup") + .arg("-dr") + .arg("RustAnalyzer") + .arg("-var") + .arg("var.RustAnalyzerDir") + .arg("-out") + .arg(exe.join("RustAnalyzerGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); + } builder.run( Command::new(&heat) .current_dir(&exe) @@ -2186,7 +2200,9 @@ impl Step for Extended { if rls_installer.is_some() { cmd.arg("-dRlsDir=rls"); } - cmd.arg("-dRustAnalyzerDir=rust-analyzer"); + if rust_analyzer_installer.is_some() { + cmd.arg("-dRustAnalyzerDir=rust-analyzer"); + } if miri_installer.is_some() { cmd.arg("-dMiriDir=miri"); } @@ -2206,7 +2222,9 @@ impl Step for Extended { if rls_installer.is_some() { candle("RlsGroup.wxs".as_ref()); } - candle("RustAnalyzerGroup.wxs".as_ref()); + if rust_analyzer_installer.is_some() { + candle("RustAnalyzerGroup.wxs".as_ref()); + } if miri_installer.is_some() { candle("MiriGroup.wxs".as_ref()); } @@ -2244,7 +2262,9 @@ impl Step for Extended { if rls_installer.is_some() { cmd.arg("RlsGroup.wixobj"); } - cmd.arg("RustAnalyzerGroup.wixobj"); + if rust_analyzer_installer.is_some() { + cmd.arg("RustAnalyzerGroup.wixobj"); + } if miri_installer.is_some() { cmd.arg("MiriGroup.wixobj"); } diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 8a6973bcdd6c9..dfaf37624e458 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -587,6 +587,7 @@ jobs: <<: [*shared-ci-variables, *dummy-variables] if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' strategy: + fast-fail: false matrix: include: ############################# diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a33f920603592..1e98ddbd7db4a 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -275,10 +275,26 @@ declare_lint_pass!(PathStatements => [PATH_STATEMENTS]); impl<'tcx> LateLintPass<'tcx> for PathStatements { fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) { - if let hir::StmtKind::Semi(ref expr) = s.kind { + if let hir::StmtKind::Semi(expr) = s.kind { if let hir::ExprKind::Path(_) = expr.kind { cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| { - lint.build("path statement with no effect").emit() + let ty = cx.typeck_results().expr_ty(expr); + if ty.needs_drop(cx.tcx, cx.param_env) { + let mut lint = lint.build("path statement drops value"); + if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) { + lint.span_suggestion( + s.span, + "use `drop` to clarify the intent", + format!("drop({});", snippet), + Applicability::MachineApplicable, + ); + } else { + lint.span_help(s.span, "use `drop` to clarify the intent"); + } + lint.emit() + } else { + lint.build("path statement with no effect").emit() + } }); } } @@ -520,7 +536,10 @@ trait UnusedDelimLint { (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right)) } - While(ref cond, ref block, ..) => { + // Do not lint `unused_braces` in `while let` expressions. + While(ref cond, ref block, ..) + if !matches!(cond.kind, Let(_, _)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => + { let left = e.span.lo() + rustc_span::BytePos(5); let right = block.span.lo(); (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right)) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 002c5f967105d..4f08452767a87 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -43,7 +43,7 @@ extern crate rustc_trait_selection; extern crate rustc_typeck; extern crate test as testing; #[macro_use] -extern crate log; +extern crate tracing as log; use std::default::Default; use std::env; diff --git a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs index 02182ec299321..8064c3a88d1d9 100644 --- a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs +++ b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.rs @@ -15,15 +15,8 @@ fn main() { while let Some(_) = ((yield)) {} //~ ERROR: unnecessary parentheses {{yield}}; //~ ERROR: unnecessary braces {( yield )}; //~ ERROR: unnecessary parentheses - - // FIXME: Reduce duplicate warnings. - // Perhaps we should tweak checks in `BlockRetValue`? - while let Some(_) = {(yield)} {} - //~^ ERROR: unnecessary braces - //~| ERROR: unnecessary parentheses - while let Some(_) = {{yield}} {} - //~^ ERROR: unnecessary braces - //~| ERROR: unnecessary braces + while let Some(_) = {(yield)} {} //~ ERROR: unnecessary parentheses + while let Some(_) = {{yield}} {} //~ ERROR: unnecessary braces // FIXME: It'd be great if we could also warn them. ((yield)); diff --git a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr index 267cc9e031a11..3f6260dc6e19e 100644 --- a/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr +++ b/src/test/ui/lint/issue-74883-unused-paren-baren-yield.stderr @@ -34,29 +34,17 @@ error: unnecessary parentheses around block return value LL | {( yield )}; | ^^^^^^^^^ help: remove these parentheses -error: unnecessary braces around `let` scrutinee expression - --> $DIR/issue-74883-unused-paren-baren-yield.rs:21:29 - | -LL | while let Some(_) = {(yield)} {} - | ^^^^^^^^^ help: remove these braces - error: unnecessary parentheses around block return value - --> $DIR/issue-74883-unused-paren-baren-yield.rs:21:30 + --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30 | LL | while let Some(_) = {(yield)} {} | ^^^^^^^ help: remove these parentheses -error: unnecessary braces around `let` scrutinee expression - --> $DIR/issue-74883-unused-paren-baren-yield.rs:24:29 - | -LL | while let Some(_) = {{yield}} {} - | ^^^^^^^^^ help: remove these braces - error: unnecessary braces around block return value - --> $DIR/issue-74883-unused-paren-baren-yield.rs:24:30 + --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30 | LL | while let Some(_) = {{yield}} {} | ^^^^^^^ help: remove these braces -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/unused-braces-while-let-with-mutable-value.rs b/src/test/ui/lint/unused-braces-while-let-with-mutable-value.rs new file mode 100644 index 0000000000000..ac547293c583a --- /dev/null +++ b/src/test/ui/lint/unused-braces-while-let-with-mutable-value.rs @@ -0,0 +1,12 @@ +// check-pass + +#![deny(unused_braces)] + +fn main() { + let mut a = Some(3); + // Shouldn't warn below `a`. + while let Some(ref mut v) = {a} { + a.as_mut().map(|a| std::mem::swap(a, v)); + break; + } +} diff --git a/src/test/ui/warn-path-statement.rs b/src/test/ui/warn-path-statement.rs index e8525f8b892d6..2435be623f310 100644 --- a/src/test/ui/warn-path-statement.rs +++ b/src/test/ui/warn-path-statement.rs @@ -1,6 +1,17 @@ // compile-flags: -D path-statements -fn main() { +struct Droppy; + +impl Drop for Droppy { + fn drop(&mut self) {} +} +fn main() { let x = 10; x; //~ ERROR path statement with no effect + + let y = Droppy; + y; //~ ERROR path statement drops value + + let z = (Droppy,); + z; //~ ERROR path statement drops value } diff --git a/src/test/ui/warn-path-statement.stderr b/src/test/ui/warn-path-statement.stderr index 30afb99e5f02c..248d2ef299be3 100644 --- a/src/test/ui/warn-path-statement.stderr +++ b/src/test/ui/warn-path-statement.stderr @@ -1,10 +1,22 @@ error: path statement with no effect - --> $DIR/warn-path-statement.rs:5:5 + --> $DIR/warn-path-statement.rs:10:5 | LL | x; | ^^ | = note: requested on the command line with `-D path-statements` -error: aborting due to previous error +error: path statement drops value + --> $DIR/warn-path-statement.rs:13:5 + | +LL | y; + | ^^ help: use `drop` to clarify the intent: `drop(y);` + +error: path statement drops value + --> $DIR/warn-path-statement.rs:16:5 + | +LL | z; + | ^^ help: use `drop` to clarify the intent: `drop(z);` + +error: aborting due to 3 previous errors