diff options
| author | Ben Kimock <kimockb@gmail.com> | 2025-03-15 05:43:22 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-15 05:43:22 +0000 |
| commit | b724fabb5f86585cd7cc2b14daa2c5a34ed779ef (patch) | |
| tree | 02971e57b3733b501a3e5165b076135a795977c0 | |
| parent | 0b643dfc799427c2657e8d5033f4284ecb1c6764 (diff) | |
| parent | 39df7ee1374e0016ca35c7430918650f21746659 (diff) | |
| download | rust-b724fabb5f86585cd7cc2b14daa2c5a34ed779ef.tar.gz rust-b724fabb5f86585cd7cc2b14daa2c5a34ed779ef.zip | |
Merge pull request #4227 from rust-lang/rustup-2025-03-15
Automatic Rustup
84 files changed, 1272 insertions, 464 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f166e0c0b41..96c0955e871 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,7 @@ jobs: timeout-minutes: 360 env: CI_JOB_NAME: ${{ matrix.name }} + CI_JOB_DOC_URL: ${{ matrix.doc_url }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} @@ -190,8 +191,20 @@ jobs: CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build - name: run the build - # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs. - run: src/ci/scripts/run-build-from-ci.sh 2>&1 + run: | + set +e + # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs. + src/ci/scripts/run-build-from-ci.sh 2>&1 + STATUS=$? + set -e + + if [[ "$STATUS" -ne 0 && -n "$CI_JOB_DOC_URL" ]]; then + echo "****************************************************************************" + echo "To find more information about this job, visit the following URL:" + echo "$CI_JOB_DOC_URL" + echo "****************************************************************************" + fi + exit ${STATUS} env: AWS_ACCESS_KEY_ID: ${{ env.CACHES_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }} diff --git a/Cargo.lock b/Cargo.lock index 942f8f43935..6d252ca8c82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6439,6 +6439,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] +name = "x" +version = "0.1.1" + +[[package]] name = "xattr" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 915ec2e00ca..16ff0f61593 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,50 +1,53 @@ [workspace] resolver = "2" members = [ +# tidy-alphabetical-start "compiler/rustc", "src/build_helper", "src/etc/test-float-parse", - "src/rustc-std-workspace/rustc-std-workspace-core", "src/rustc-std-workspace/rustc-std-workspace-alloc", + "src/rustc-std-workspace/rustc-std-workspace-core", "src/rustc-std-workspace/rustc-std-workspace-std", "src/rustdoc-json-types", + "src/tools/build-manifest", + "src/tools/bump-stage0", "src/tools/cargotest", "src/tools/clippy", "src/tools/clippy/clippy_dev", + "src/tools/collect-license-metadata", "src/tools/compiletest", - "src/tools/run-make-support", + "src/tools/coverage-dump", + "src/tools/features-status-dump", + "src/tools/generate-copyright", + "src/tools/generate-windows-sys", + "src/tools/html-checker", + "src/tools/jsondocck", + "src/tools/jsondoclint", "src/tools/linkchecker", "src/tools/lint-docs", + "src/tools/lld-wrapper", + "src/tools/llvm-bitcode-linker", + "src/tools/miri", + "src/tools/miri/cargo-miri", "src/tools/miropt-test-tools", - "src/tools/unstable-book-gen", - "src/tools/tidy", - "src/tools/tier-check", - "src/tools/build-manifest", + "src/tools/opt-dist", "src/tools/remote-test-client", "src/tools/remote-test-server", + "src/tools/replace-version-placeholder", + "src/tools/run-make-support", "src/tools/rust-installer", "src/tools/rustdoc", - "src/tools/rustfmt", - "src/tools/miri", - "src/tools/miri/cargo-miri", + "src/tools/rustdoc-gui-test", "src/tools/rustdoc-themes", - "src/tools/unicode-table-generator", - "src/tools/jsondocck", - "src/tools/jsondoclint", - "src/tools/llvm-bitcode-linker", - "src/tools/html-checker", - "src/tools/bump-stage0", - "src/tools/replace-version-placeholder", - "src/tools/lld-wrapper", - "src/tools/collect-license-metadata", - "src/tools/generate-copyright", + "src/tools/rustfmt", "src/tools/suggest-tests", - "src/tools/generate-windows-sys", - "src/tools/rustdoc-gui-test", - "src/tools/opt-dist", - "src/tools/coverage-dump", + "src/tools/tidy", + "src/tools/tier-check", + "src/tools/unicode-table-generator", + "src/tools/unstable-book-gen", "src/tools/wasm-component-ld", - "src/tools/features-status-dump", + "src/tools/x", +# tidy-alphabetical-end ] exclude = [ @@ -55,11 +58,6 @@ exclude = [ "tests/rustdoc-gui", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", - # The `x` binary is a thin wrapper that calls `x.py`, which initializes - # submodules, before which workspace members cannot be invoked because - # not all `Cargo.toml` files are available, so we exclude the `x` binary, - # so it can be invoked before the current checkout is set up. - "src/tools/x", ] [profile.release.package.rustc-rayon-core] diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1b831c454e6..5b7545b3396 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1657,7 +1657,7 @@ pub enum ExprKind { Try(P<Expr>), /// A `yield`, with an optional value to be yielded. - Yield(Option<P<Expr>>), + Yield(YieldKind), /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever), /// with an optional value to be returned. @@ -1903,6 +1903,44 @@ pub enum MatchKind { Postfix, } +/// The kind of yield expression +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum YieldKind { + /// yield expr { ... } + Prefix(Option<P<Expr>>), + /// expr.yield { ... } + Postfix(P<Expr>), +} + +impl YieldKind { + /// Returns the expression inside the yield expression, if any. + /// + /// For postfix yields, this is guaranteed to be `Some`. + pub const fn expr(&self) -> Option<&P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_ref(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns a mutable reference to the expression being yielded, if any. + pub const fn expr_mut(&mut self) -> Option<&mut P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_mut(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns true if both yields are prefix or both are postfix. + pub const fn same_kind(&self, other: &Self) -> bool { + match (self, other) { + (YieldKind::Prefix(_), YieldKind::Prefix(_)) => true, + (YieldKind::Postfix(_), YieldKind::Postfix(_)) => true, + _ => false, + } + } +} + /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4a1636e6aec..b159e136245 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1813,8 +1813,11 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token ExprKind::Paren(expr) => { vis.visit_expr(expr); } - ExprKind::Yield(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); + ExprKind::Yield(kind) => { + let expr = kind.expr_mut(); + if let Some(expr) = expr { + vis.visit_expr(expr); + } } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index e43d78f6e72..989ebe14bf8 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -182,11 +182,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Range(_, Some(e), _) | Ret(Some(e)) | Unary(_, e) - | Yield(Some(e)) | Yeet(Some(e)) | Become(e) => { expr = e; } + Yield(kind) => match kind.expr() { + Some(e) => expr = e, + None => break None, + }, Closure(closure) => { expr = &closure.body; } @@ -217,7 +220,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { Break(_, None) | Range(_, None, _) | Ret(None) - | Yield(None) | Array(_) | Call(_, _) | MethodCall(_) @@ -237,7 +239,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Yeet(None) | UnsafeBinderCast(..) | Err(_) - | Dummy => break None, + | Dummy => { + break None; + } } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index cfcb0e23cb5..ce8d6df75af 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1269,8 +1269,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_ty(container)); walk_list!(visitor, visit_ident, fields.iter()); } - ExprKind::Yield(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); + ExprKind::Yield(kind) => { + visit_opt!(visitor, visit_expr, kind.expr()); } ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5bb6704dde4..7f3d060bb8a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -351,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), + ExprKind::Yield(kind) => self.lower_expr_yield(e.span, kind.expr().map(|x| &**x)), ExprKind::Err(guar) => hir::ExprKind::Err(*guar), ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast( diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e3c41f117ab..7d9dc89bd75 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, - FormatDebugHex, FormatSign, FormatTrait, token, + FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, }; use crate::pp::Breaks::Inconsistent; @@ -761,7 +761,7 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); self.pclose(); } - ast::ExprKind::Yield(e) => { + ast::ExprKind::Yield(YieldKind::Prefix(e)) => { self.word("yield"); if let Some(expr) = e { @@ -773,6 +773,14 @@ impl<'a> State<'a> { ); } } + ast::ExprKind::Yield(YieldKind::Postfix(e)) => { + self.print_expr_cond_paren( + e, + e.precedence() < ExprPrecedence::Unambiguous, + fixup.leftmost_subexpression_with_dot(), + ); + self.word(".yield"); + } ast::ExprKind::Try(e) => { self.print_expr_cond_paren( e, diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 6735ae024d1..75f3a3c1972 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1031,7 +1031,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1052,7 +1052,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1073,7 +1073,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1094,7 +1094,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs index 63023fdba20..383d0579e52 100644 --- a/compiler/rustc_codegen_ssa/src/back/command.rs +++ b/compiler/rustc_codegen_ssa/src/back/command.rs @@ -143,13 +143,6 @@ impl Command { return false; } - // Right now LLD doesn't support the `@` syntax of passing an argument - // through files, so regardless of the platform we try to go to the OS - // on this one. - if let Program::Lld(..) = self.program { - return false; - } - // Ok so on Windows to spawn a process is 32,768 characters in its // command line [1]. Unfortunately we don't actually have access to that // as it's calculated just before spawning. Instead we perform a diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 8bc6f9e6fe3..63025a4574f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -433,6 +433,40 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } // These are all AtomicRMW ops + "max" | "min" => { + let atom_op = if instruction == "max" { + AtomicRmwBinOp::AtomicMax + } else { + AtomicRmwBinOp::AtomicMin + }; + + let ty = fn_args.type_at(0); + if matches!(ty.kind(), ty::Int(_)) { + let ptr = args[0].immediate(); + let val = args[1].immediate(); + bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering)) + } else { + invalid_monomorphization(ty); + return Ok(()); + } + } + "umax" | "umin" => { + let atom_op = if instruction == "umax" { + AtomicRmwBinOp::AtomicUMax + } else { + AtomicRmwBinOp::AtomicUMin + }; + + let ty = fn_args.type_at(0); + if matches!(ty.kind(), ty::Uint(_)) { + let ptr = args[0].immediate(); + let val = args[1].immediate(); + bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering)) + } else { + invalid_monomorphization(ty); + return Ok(()); + } + } op => { let atom_op = match op { "xchg" => AtomicRmwBinOp::AtomicXchg, @@ -442,10 +476,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "nand" => AtomicRmwBinOp::AtomicNand, "or" => AtomicRmwBinOp::AtomicOr, "xor" => AtomicRmwBinOp::AtomicXor, - "max" => AtomicRmwBinOp::AtomicMax, - "min" => AtomicRmwBinOp::AtomicMin, - "umax" => AtomicRmwBinOp::AtomicUMax, - "umin" => AtomicRmwBinOp::AtomicUMin, _ => bx.sess().dcx().emit_fatal(errors::UnknownAtomicOperation), }; diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 63e4a8fb44b..35e687f2b0f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1840,7 +1840,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty = self.pat_ty_adjusted(subpat)?; let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability); // A deref pattern generates a temporary. - let place = self.cat_rvalue(pat.hir_id, ty); + let base = self.cat_rvalue(pat.hir_id, ty); + let place = self.cat_deref(pat.hir_id, base)?; self.cat_pattern(place, subpat, op)?; } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index aa6eef906ea..8718fb807ec 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -299,6 +299,11 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { intravisit::walk_expr(self, e); } + fn visit_pat_field(&mut self, f: &'tcx hir::PatField<'tcx>) -> Self::Result { + self.add_id(f.hir_id); + intravisit::walk_pat_field(self, f); + } + fn visit_expr_field(&mut self, f: &'tcx hir::ExprField<'tcx>) { self.add_id(f.hir_id); intravisit::walk_expr_field(self, f); diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index b23d8b9e737..00a8293966b 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -37,29 +37,11 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { /// and even the full `Inline` doesn't call `visit_body`, so there's nowhere /// to put this logic in the visitor. pub(super) fn add_function_level_costs(&mut self) { - fn is_call_like(bbd: &BasicBlockData<'_>) -> bool { - use TerminatorKind::*; - match bbd.terminator().kind { - Call { .. } | TailCall { .. } | Drop { .. } | Assert { .. } | InlineAsm { .. } => { - true - } - - Goto { .. } - | SwitchInt { .. } - | UnwindResume - | UnwindTerminate(_) - | Return - | Unreachable => false, - - Yield { .. } | CoroutineDrop | FalseEdge { .. } | FalseUnwind { .. } => { - unreachable!() - } - } - } - // If the only has one Call (or similar), inlining isn't increasing the total // number of calls, so give extra encouragement to inlining that. - if self.callee_body.basic_blocks.iter().filter(|bbd| is_call_like(bbd)).count() == 1 { + if self.callee_body.basic_blocks.iter().filter(|bbd| is_call_like(bbd.terminator())).count() + == 1 + { self.bonus += CALL_PENALTY; } } @@ -193,3 +175,26 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } } + +/// A terminator that's more call-like (might do a bunch of work, might panic, etc) +/// than it is goto-/return-like (no side effects, etc). +/// +/// Used to treat multi-call functions (which could inline exponentially) +/// different from those that only do one or none of these "complex" things. +pub(super) fn is_call_like(terminator: &Terminator<'_>) -> bool { + use TerminatorKind::*; + match terminator.kind { + Call { .. } | TailCall { .. } | Drop { .. } | Assert { .. } | InlineAsm { .. } => true, + + Goto { .. } + | SwitchInt { .. } + | UnwindResume + | UnwindTerminate(_) + | Return + | Unreachable => false, + + Yield { .. } | CoroutineDrop | FalseEdge { .. } | FalseUnwind { .. } => { + unreachable!() + } + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0183ba19475..0ab24e48d44 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1,5 +1,6 @@ //! Inlining pass for MIR functions. +use std::assert_matches::debug_assert_matches; use std::iter; use std::ops::{Range, RangeFrom}; @@ -18,7 +19,7 @@ use rustc_session::config::{DebugInfo, OptLevel}; use rustc_span::source_map::Spanned; use tracing::{debug, instrument, trace, trace_span}; -use crate::cost_checker::CostChecker; +use crate::cost_checker::{CostChecker, is_call_like}; use crate::deref_separator::deref_finder; use crate::simplify::simplify_cfg; use crate::validate::validate_types; @@ -26,6 +27,7 @@ use crate::{check_inline, util}; pub(crate) mod cycle; +const HISTORY_DEPTH_LIMIT: usize = 20; const TOP_DOWN_DEPTH_LIMIT: usize = 5; #[derive(Clone, Debug)] @@ -117,6 +119,11 @@ trait Inliner<'tcx> { /// Should inlining happen for a given callee? fn should_inline_for_callee(&self, def_id: DefId) -> bool; + fn check_codegen_attributes_extra( + &self, + callee_attrs: &CodegenFnAttrs, + ) -> Result<(), &'static str>; + fn check_caller_mir_body(&self, body: &Body<'tcx>) -> bool; /// Returns inlining decision that is based on the examination of callee MIR body. @@ -128,10 +135,6 @@ trait Inliner<'tcx> { callee_attrs: &CodegenFnAttrs, ) -> Result<(), &'static str>; - // How many callsites in a body are we allowed to inline? We need to limit this in order - // to prevent super-linear growth in MIR size. - fn inline_limit_for_block(&self) -> Option<usize>; - /// Called when inlining succeeds. fn on_inline_success( &mut self, @@ -142,9 +145,6 @@ trait Inliner<'tcx> { /// Called when inlining failed or was not performed. fn on_inline_failure(&self, callsite: &CallSite<'tcx>, reason: &'static str); - - /// Called when the inline limit for a body is reached. - fn on_inline_limit_reached(&self) -> bool; } struct ForceInliner<'tcx> { @@ -191,6 +191,14 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { ForceInline::should_run_pass_for_callee(self.tcx(), def_id) } + fn check_codegen_attributes_extra( + &self, + callee_attrs: &CodegenFnAttrs, + ) -> Result<(), &'static str> { + debug_assert_matches!(callee_attrs.inline, InlineAttr::Force { .. }); + Ok(()) + } + fn check_caller_mir_body(&self, _: &Body<'tcx>) -> bool { true } @@ -224,10 +232,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { } } - fn inline_limit_for_block(&self) -> Option<usize> { - Some(usize::MAX) - } - fn on_inline_success( &mut self, callsite: &CallSite<'tcx>, @@ -261,10 +265,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { justification: justification.map(|sym| crate::errors::ForceInlineJustification { sym }), }); } - - fn on_inline_limit_reached(&self) -> bool { - false - } } struct NormalInliner<'tcx> { @@ -278,6 +278,10 @@ struct NormalInliner<'tcx> { /// The number of `DefId`s is finite, so checking history is enough /// to ensure that we do not loop endlessly while inlining. history: Vec<DefId>, + /// How many (multi-call) callsites have we inlined for the top-level call? + /// + /// We need to limit this in order to prevent super-linear growth in MIR size. + top_down_counter: usize, /// Indicates that the caller body has been modified. changed: bool, /// Indicates that the caller is #[inline] and just calls another function, @@ -285,6 +289,12 @@ struct NormalInliner<'tcx> { caller_is_inline_forwarder: bool, } +impl<'tcx> NormalInliner<'tcx> { + fn past_depth_limit(&self) -> bool { + self.history.len() > HISTORY_DEPTH_LIMIT || self.top_down_counter > TOP_DOWN_DEPTH_LIMIT + } +} + impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { fn new(tcx: TyCtxt<'tcx>, def_id: DefId, body: &Body<'tcx>) -> Self { let typing_env = body.typing_env(tcx); @@ -295,6 +305,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { typing_env, def_id, history: Vec::new(), + top_down_counter: 0, changed: false, caller_is_inline_forwarder: matches!( codegen_fn_attrs.inline, @@ -327,6 +338,17 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { true } + fn check_codegen_attributes_extra( + &self, + callee_attrs: &CodegenFnAttrs, + ) -> Result<(), &'static str> { + if self.past_depth_limit() && matches!(callee_attrs.inline, InlineAttr::None) { + Err("Past depth limit so not inspecting unmarked callee") + } else { + Ok(()) + } + } + fn check_caller_mir_body(&self, body: &Body<'tcx>) -> bool { // Avoid inlining into coroutines, since their `optimized_mir` is used for layout computation, // which can create a cycle, even when no attempt is made to inline the function in the other @@ -351,7 +373,11 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { return Err("body has errors"); } - let mut threshold = if self.caller_is_inline_forwarder { + if self.past_depth_limit() && callee_body.basic_blocks.len() > 1 { + return Err("Not inlining multi-block body as we're past a depth limit"); + } + + let mut threshold = if self.caller_is_inline_forwarder || self.past_depth_limit() { tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30) } else if tcx.cross_crate_inlinable(callsite.callee.def_id()) { tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100) @@ -431,14 +457,6 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { } } - fn inline_limit_for_block(&self) -> Option<usize> { - match self.history.len() { - 0 => Some(usize::MAX), - 1..=TOP_DOWN_DEPTH_LIMIT => Some(1), - _ => None, - } - } - fn on_inline_success( &mut self, callsite: &CallSite<'tcx>, @@ -447,13 +465,21 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { ) { self.changed = true; + let new_calls_count = new_blocks + .clone() + .filter(|&bb| is_call_like(caller_body.basic_blocks[bb].terminator())) + .count(); + if new_calls_count > 1 { + self.top_down_counter += 1; + } + self.history.push(callsite.callee.def_id()); process_blocks(self, caller_body, new_blocks); self.history.pop(); - } - fn on_inline_limit_reached(&self) -> bool { - true + if self.history.is_empty() { + self.top_down_counter = 0; + } } fn on_inline_failure(&self, _: &CallSite<'tcx>, _: &'static str) {} @@ -482,8 +508,6 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>( caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>, ) { - let Some(inline_limit) = inliner.inline_limit_for_block() else { return }; - let mut inlined_count = 0; for bb in blocks { let bb_data = &caller_body[bb]; if bb_data.is_cleanup { @@ -505,13 +529,6 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>( Ok(new_blocks) => { debug!("inlined {}", callsite.callee); inliner.on_inline_success(&callsite, caller_body, new_blocks); - - inlined_count += 1; - if inlined_count == inline_limit { - if inliner.on_inline_limit_reached() { - return; - } - } } } } @@ -584,6 +601,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id()); check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?; check_codegen_attributes(inliner, callsite, callee_attrs)?; + inliner.check_codegen_attributes_extra(callee_attrs)?; let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; @@ -770,6 +788,8 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>( return Err("has DoNotOptimize attribute"); } + inliner.check_codegen_attributes_extra(callee_attrs)?; + // Reachability pass defines which functions are eligible for inlining. Generally inlining // other functions is incorrect because they could reference symbols that aren't exported. let is_generic = callsite.callee.args.non_erasable_generics().next().is_some(); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9b2d562a69e..fc9a511d56a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,6 +17,7 @@ use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, + YieldKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1310,6 +1311,15 @@ impl<'a> Parser<'a> { return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); } + // Parse a postfix `yield`. + if self.eat_keyword(exp!(Yield)) { + let yield_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::yield_expr, yield_span); + return Ok( + self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg))) + ); + } + let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]); @@ -1884,7 +1894,7 @@ impl<'a> Parser<'a> { /// Parse `"yield" expr?`. fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> { let lo = self.prev_token.span; - let kind = ExprKind::Yield(self.parse_expr_opt()?); + let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?)); let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::yield_expr, span); let expr = self.mk_expr(span, kind); diff --git a/compiler/rustc_target/src/spec/base/fuchsia.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs index 9deafcac27f..92cb0299ddb 100644 --- a/compiler/rustc_target/src/spec/base/fuchsia.rs +++ b/compiler/rustc_target/src/spec/base/fuchsia.rs @@ -7,7 +7,7 @@ pub(crate) fn opts() -> TargetOptions { // now. When using clang as the linker it will supply these options for us, // so we only list them for ld/lld. // - // https://github.com/llvm/llvm-project/blob/db9322b2066c55254e7691efeab863f43bfcc084/clang/lib/Driver/ToolChains/Fuchsia.cpp#L31 + // https://github.com/llvm/llvm-project/blob/0419db6b95e246fe9dc90b5795beb77c393eb2ce/clang/lib/Driver/ToolChains/Fuchsia.cpp#L32 let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), &[ @@ -18,9 +18,13 @@ pub(crate) fn opts() -> TargetOptions { "-z", "now", "-z", + "start-stop-visibility=hidden", + "-z", "rodynamic", "-z", "separate-loadable-segments", + "-z", + "rel", "--pack-dyn-relocs=relr", ], ); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 23ed92e62b8..8366b6d9bd8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -1,6 +1,28 @@ -use crate::spec::{SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{ + Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base, +}; pub(crate) fn target() -> Target { + let mut base = base::fuchsia::opts(); + base.cpu = "generic".into(); + base.features = "+v8a,+crc,+aes,+sha2,+neon".into(); + base.max_atomic_width = Some(128); + base.stack_probes = StackProbeType::Inline; + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::SHADOWCALLSTACK; + base.supports_xray = true; + + base.add_pre_link_args( + LinkerFlavor::Gnu(Cc::No, Lld::No), + &[ + "--execute-only", + // Enable the Cortex-A53 errata 843419 mitigation by default + "--fix-cortex-a53-843419", + ], + ); + Target { llvm_target: "aarch64-unknown-fuchsia".into(), metadata: TargetMetadata { @@ -12,14 +34,6 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), - options: TargetOptions { - features: "+v8a".into(), - max_atomic_width: Some(128), - stack_probes: StackProbeType::Inline, - supported_sanitizers: SanitizerSet::ADDRESS - | SanitizerSet::CFI - | SanitizerSet::SHADOWCALLSTACK, - ..base::fuchsia::opts() - }, + options: base, } } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs index d673936f5f8..e260237ca77 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs @@ -1,6 +1,16 @@ -use crate::spec::{CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, StackProbeType, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { + let mut base = base::fuchsia::opts(); + base.code_model = Some(CodeModel::Medium); + base.cpu = "generic-rv64".into(); + base.features = "+m,+a,+f,+d,+c".into(); + base.llvm_abiname = "lp64d".into(); + base.max_atomic_width = Some(64); + base.stack_probes = StackProbeType::Inline; + base.supported_sanitizers = SanitizerSet::SHADOWCALLSTACK; + base.supports_xray = true; + Target { llvm_target: "riscv64-unknown-fuchsia".into(), metadata: TargetMetadata { @@ -12,14 +22,6 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), arch: "riscv64".into(), - options: TargetOptions { - code_model: Some(CodeModel::Medium), - cpu: "generic-rv64".into(), - features: "+m,+a,+f,+d,+c".into(), - llvm_abiname: "lp64d".into(), - max_atomic_width: Some(64), - supported_sanitizers: SanitizerSet::SHADOWCALLSTACK, - ..base::fuchsia::opts() - }, + options: base, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index d41c696ac23..d7253da7e8d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -4,7 +4,10 @@ pub(crate) fn target() -> Target { let mut base = base::fuchsia::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; - base.max_atomic_width = Some(64); + // See https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0073_x86_64_platform_requirement, + // which corresponds to x86-64-v2. + base.features = "+cx16,+sahf,+popcnt,+sse3,+sse4.1,+sse4.2,+ssse3".into(); + base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK; base.supports_xray = true; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ead7b2d2965..48b265fabc7 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -90,6 +90,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { // memory, which is not valid for either `&` or `&mut`. /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -99,6 +100,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { #[rustc_nounwind] pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -108,6 +110,7 @@ pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -117,6 +120,7 @@ pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -126,6 +130,7 @@ pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -135,6 +140,7 @@ pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -144,6 +150,7 @@ pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -153,6 +160,7 @@ pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -162,6 +170,7 @@ pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -171,6 +180,7 @@ pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -180,6 +190,7 @@ pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -189,6 +200,7 @@ pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -198,6 +210,7 @@ pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -207,6 +220,7 @@ pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) - #[rustc_nounwind] pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -216,6 +230,7 @@ pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) #[rustc_nounwind] pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method by passing @@ -226,6 +241,7 @@ pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) pub unsafe fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -239,6 +255,7 @@ pub unsafe fn atomic_cxchgweak_relaxed_relaxed<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -252,6 +269,7 @@ pub unsafe fn atomic_cxchgweak_relaxed_acquire<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -261,6 +279,7 @@ pub unsafe fn atomic_cxchgweak_relaxed_acquire<T: Copy>( #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -274,6 +293,7 @@ pub unsafe fn atomic_cxchgweak_acquire_relaxed<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -287,6 +307,7 @@ pub unsafe fn atomic_cxchgweak_acquire_acquire<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -296,6 +317,7 @@ pub unsafe fn atomic_cxchgweak_acquire_acquire<T: Copy>( #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -309,6 +331,7 @@ pub unsafe fn atomic_cxchgweak_release_relaxed<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -322,6 +345,7 @@ pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>( _src: T, ) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -331,6 +355,7 @@ pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>( #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -340,6 +365,7 @@ pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -349,6 +375,7 @@ pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -358,6 +385,7 @@ pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -367,6 +395,7 @@ pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -376,6 +405,7 @@ pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method by passing @@ -386,6 +416,7 @@ pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool); /// Loads the current value of the pointer. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing @@ -394,6 +425,7 @@ pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: #[rustc_nounwind] pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T; /// Loads the current value of the pointer. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing @@ -402,6 +434,7 @@ pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T; #[rustc_nounwind] pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T; /// Loads the current value of the pointer. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method by passing @@ -417,6 +450,7 @@ pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T; pub unsafe fn atomic_load_unordered<T: Copy>(src: *const T) -> T; /// Stores the value at the specified memory location. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing @@ -425,6 +459,7 @@ pub unsafe fn atomic_load_unordered<T: Copy>(src: *const T) -> T; #[rustc_nounwind] pub unsafe fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing @@ -433,6 +468,7 @@ pub unsafe fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T); #[rustc_nounwind] pub unsafe fn atomic_store_release<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method by passing @@ -448,6 +484,7 @@ pub unsafe fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T); pub unsafe fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T); /// Stores the value at the specified memory location, returning the old value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing @@ -456,6 +493,7 @@ pub unsafe fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T); #[rustc_nounwind] pub unsafe fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing @@ -464,6 +502,7 @@ pub unsafe fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing @@ -472,6 +511,7 @@ pub unsafe fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing @@ -480,6 +520,7 @@ pub unsafe fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. +/// `T` must be an integer or pointer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method by passing @@ -489,6 +530,9 @@ pub unsafe fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing @@ -497,6 +541,9 @@ pub unsafe fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing @@ -505,6 +552,9 @@ pub unsafe fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing @@ -513,6 +563,9 @@ pub unsafe fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing @@ -521,6 +574,9 @@ pub unsafe fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method by passing @@ -530,6 +586,9 @@ pub unsafe fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing @@ -538,6 +597,9 @@ pub unsafe fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing @@ -546,6 +608,9 @@ pub unsafe fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing @@ -554,6 +619,9 @@ pub unsafe fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing @@ -562,6 +630,9 @@ pub unsafe fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method by passing @@ -571,6 +642,9 @@ pub unsafe fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing @@ -579,6 +653,9 @@ pub unsafe fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing @@ -587,6 +664,9 @@ pub unsafe fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing @@ -595,6 +675,9 @@ pub unsafe fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing @@ -603,6 +686,9 @@ pub unsafe fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method by passing @@ -612,6 +698,9 @@ pub unsafe fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing @@ -620,6 +709,9 @@ pub unsafe fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing @@ -628,6 +720,9 @@ pub unsafe fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing @@ -636,6 +731,9 @@ pub unsafe fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing @@ -644,6 +742,9 @@ pub unsafe fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`AtomicBool`] type via the `fetch_nand` method by passing @@ -653,6 +754,9 @@ pub unsafe fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing @@ -661,6 +765,9 @@ pub unsafe fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing @@ -669,6 +776,9 @@ pub unsafe fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing @@ -677,6 +787,9 @@ pub unsafe fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing @@ -685,6 +798,9 @@ pub unsafe fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method by passing @@ -694,6 +810,9 @@ pub unsafe fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing @@ -702,6 +821,9 @@ pub unsafe fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing @@ -710,6 +832,9 @@ pub unsafe fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing @@ -718,6 +843,9 @@ pub unsafe fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing @@ -726,6 +854,9 @@ pub unsafe fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. +/// `T` must be an integer or pointer type. +/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new +/// value stored at `*dst` will have the provenance of the old value stored there. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method by passing @@ -735,6 +866,7 @@ pub unsafe fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing @@ -743,6 +875,7 @@ pub unsafe fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing @@ -751,6 +884,7 @@ pub unsafe fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing @@ -759,6 +893,7 @@ pub unsafe fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing @@ -766,7 +901,8 @@ pub unsafe fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T; -/// Maximum with the current value. +/// Maximum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method by passing @@ -776,6 +912,7 @@ pub unsafe fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing @@ -784,6 +921,7 @@ pub unsafe fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing @@ -792,6 +930,7 @@ pub unsafe fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing @@ -800,6 +939,7 @@ pub unsafe fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing @@ -808,6 +948,7 @@ pub unsafe fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using a signed comparison. +/// `T` must be a signed integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method by passing @@ -817,6 +958,7 @@ pub unsafe fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing @@ -825,6 +967,7 @@ pub unsafe fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing @@ -833,6 +976,7 @@ pub unsafe fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing @@ -841,6 +985,7 @@ pub unsafe fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing @@ -849,6 +994,7 @@ pub unsafe fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method by passing @@ -858,6 +1004,7 @@ pub unsafe fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T; pub unsafe fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing @@ -866,6 +1013,7 @@ pub unsafe fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing @@ -874,6 +1022,7 @@ pub unsafe fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing @@ -882,6 +1031,7 @@ pub unsafe fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing @@ -890,6 +1040,7 @@ pub unsafe fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T; #[rustc_nounwind] pub unsafe fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsigned comparison. +/// `T` must be an unsigned integer type. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method by passing diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index caab7a6ddb5..1494d7aca15 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -856,8 +856,13 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T { // such that the old value is not duplicated. Nothing is dropped and // nothing here can panic. unsafe { - let result = ptr::read(dest); - ptr::write(dest, src); + // Ideally we wouldn't use the intrinsics here, but going through the + // `ptr` methods introduces two unnecessary UbChecks, so until we can + // remove those for pointers that come from references, this uses the + // intrinsics instead so this stays very cheap in MIR (and debug). + + let result = crate::intrinsics::read_via_copy(dest); + crate::intrinsics::write_via_move(dest, src); result } } diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index 57f47e66e81..21753d00924 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -8,11 +8,15 @@ use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and /// [`SocketAddrV6`]'s respective documentation for more details. /// -/// The size of a `SocketAddr` instance may vary depending on the target operating -/// system. -/// /// [IP address]: IpAddr /// +/// # Portability +/// +/// `SocketAddr` is intended to be a portable representation of socket addresses and is likely not +/// the same as the internal socket address type used by the target operating system's API. Like all +/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon +/// between builds. +/// /// # Examples /// /// ``` @@ -42,13 +46,16 @@ pub enum SocketAddr { /// /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// -/// The size of a `SocketAddrV4` struct may vary depending on the target operating -/// system. Do not assume that this type has the same memory layout as the underlying -/// system representation. -/// /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 /// [`IPv4` address]: Ipv4Addr /// +/// # Portability +/// +/// `SocketAddrV4` is intended to be a portable representation of socket addresses and is likely not +/// the same as the internal socket address type used by the target operating system's API. Like all +/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon +/// between builds. +/// /// # Textual representation /// /// `SocketAddrV4` provides a [`FromStr`](crate::str::FromStr) implementation. @@ -84,13 +91,16 @@ pub struct SocketAddrV4 { /// /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. /// -/// The size of a `SocketAddrV6` struct may vary depending on the target operating -/// system. Do not assume that this type has the same memory layout as the underlying -/// system representation. -/// /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 /// [`IPv6` address]: Ipv6Addr /// +/// # Portability +/// +/// `SocketAddrV6` is intended to be a portable representation of socket addresses and is likely not +/// the same as the internal socket address type used by the target operating system's API. Like all +/// `repr(Rust)` structs, however, its exact layout remains undefined and should not be relied upon +/// between builds. +/// /// # Textual representation /// /// `SocketAddrV6` provides a [`FromStr`](crate::str::FromStr) implementation, diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index daba918af82..2487f5a2a50 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -208,20 +208,32 @@ use crate::ops::Index; /// # Usage in `const` and `static` /// /// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed, -/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the -/// initializer of a `const` or `static` item, you will have to use a different hasher that does not -/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this -/// way is not resistant against HashDoS!** +/// which means that `HashMap::new` normally cannot be used in a `const` or `static` initializer. /// +/// However, if you need to use a `HashMap` in a `const` or `static` initializer while retaining +/// random seed generation, you can wrap the `HashMap` in [`LazyLock`]. +/// +/// Alternatively, you can construct a `HashMap` in a `const` or `static` initializer using a different +/// hasher that does not rely on a random seed. **Be aware that a `HashMap` created this way is not +/// resistant to HashDoS attacks!** +/// +/// [`LazyLock`]: crate::sync::LazyLock /// ```rust /// use std::collections::HashMap; /// use std::hash::{BuildHasherDefault, DefaultHasher}; -/// use std::sync::Mutex; +/// use std::sync::{LazyLock, Mutex}; /// -/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> = +/// // HashMaps with a fixed, non-random hasher +/// const NONRANDOM_EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> = /// HashMap::with_hasher(BuildHasherDefault::new()); -/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> = +/// static NONRANDOM_MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> = /// Mutex::new(HashMap::with_hasher(BuildHasherDefault::new())); +/// +/// // HashMaps using LazyLock to retain random seeding +/// const RANDOM_EMPTY_MAP: LazyLock<HashMap<String, Vec<i32>>> = +/// LazyLock::new(HashMap::new); +/// static RANDOM_MAP: LazyLock<Mutex<HashMap<String, Vec<i32>>>> = +/// LazyLock::new(|| Mutex::new(HashMap::new())); /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")] diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 04a45fd035a..0427feb2955 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -276,63 +276,89 @@ impl FileExt for fs::File { } /// Unix-specific extensions to [`fs::Permissions`]. +/// +/// # Examples +/// +/// ```no_run +/// use std::fs::{File, Permissions}; +/// use std::io::{ErrorKind, Result as IoResult}; +/// use std::os::unix::fs::PermissionsExt; +/// +/// fn main() -> IoResult<()> { +/// let name = "test_file_for_permissions"; +/// +/// // make sure file does not exist +/// let _ = std::fs::remove_file(name); +/// assert_eq!( +/// File::open(name).unwrap_err().kind(), +/// ErrorKind::NotFound, +/// "file already exists" +/// ); +/// +/// // full read/write/execute mode bits for owner of file +/// // that we want to add to existing mode bits +/// let my_mode = 0o700; +/// +/// // create new file with specified permissions +/// { +/// let file = File::create(name)?; +/// let mut permissions = file.metadata()?.permissions(); +/// eprintln!("Current permissions: {:o}", permissions.mode()); +/// +/// // make sure new permissions are not already set +/// assert!( +/// permissions.mode() & my_mode != my_mode, +/// "permissions already set" +/// ); +/// +/// // either use `set_mode` to change an existing Permissions struct +/// permissions.set_mode(permissions.mode() | my_mode); +/// +/// // or use `from_mode` to construct a new Permissions struct +/// permissions = Permissions::from_mode(permissions.mode() | my_mode); +/// +/// // write new permissions to file +/// file.set_permissions(permissions)?; +/// } +/// +/// let permissions = File::open(name)?.metadata()?.permissions(); +/// eprintln!("New permissions: {:o}", permissions.mode()); +/// +/// // assert new permissions were set +/// assert_eq!( +/// permissions.mode() & my_mode, +/// my_mode, +/// "new permissions not set" +/// ); +/// Ok(()) +/// } +/// ``` +/// +/// ```no_run +/// use std::fs::Permissions; +/// use std::os::unix::fs::PermissionsExt; +/// +/// // read/write for owner and read for others +/// let my_mode = 0o644; +/// let mut permissions = Permissions::from_mode(my_mode); +/// assert_eq!(permissions.mode(), my_mode); +/// +/// // read/write/execute for owner +/// let other_mode = 0o700; +/// permissions.set_mode(other_mode); +/// assert_eq!(permissions.mode(), other_mode); +/// ``` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { - /// Returns the underlying raw `st_mode` bits that contain the standard - /// Unix permissions for this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; - /// - /// fn main() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); - /// - /// println!("permissions: {:o}", permissions.mode()); - /// Ok(()) - /// } - /// ``` + /// Returns the mode permission bits #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; - /// Sets the underlying raw bits for this set of permissions. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; - /// - /// fn main() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); - /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// Ok(()) - /// } - /// ``` + /// Sets the mode permission bits. #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); - /// Creates a new instance of `Permissions` from the given set of Unix - /// permission bits. - /// - /// # Examples - /// - /// ``` - /// use std::fs::Permissions; - /// use std::os::unix::fs::PermissionsExt; - /// - /// // Read/write for owner and read for others. - /// let permissions = Permissions::from_mode(0o644); - /// assert_eq!(permissions.mode(), 0o644); - /// ``` + /// Creates a new instance from the given mode permission bits. #[stable(feature = "fs_ext", since = "1.1.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "permissions_from_mode")] fn from_mode(mode: u32) -> Self; diff --git a/library/std/src/path.rs b/library/std/src/path.rs index f9f3b488f0d..980213be7ea 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -294,11 +294,6 @@ where } } -// Detect scheme on Redox -pub(crate) fn has_redox_scheme(s: &[u8]) -> bool { - cfg!(target_os = "redox") && s.contains(&b':') -} - //////////////////////////////////////////////////////////////////////////////// // Cross-platform, iterator-independent parsing //////////////////////////////////////////////////////////////////////////////// @@ -2834,8 +2829,7 @@ impl Path { Components { path: self.as_u8_slice(), prefix, - has_physical_root: has_physical_root(self.as_u8_slice(), prefix) - || has_redox_scheme(self.as_u8_slice()), + has_physical_root: has_physical_root(self.as_u8_slice(), prefix), front: State::Prefix, back: State::Body, } diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 0a2a8f5ef67..60c33c637d7 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -216,6 +216,60 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R Err(io::const_error!(io::ErrorKind::NotFound, "no device path to text protocol found")) } +fn device_node_to_text(path: NonNull<device_path::Protocol>) -> io::Result<OsString> { + fn node_to_text( + protocol: NonNull<device_path_to_text::Protocol>, + path: NonNull<device_path::Protocol>, + ) -> io::Result<OsString> { + let path_ptr: *mut r_efi::efi::Char16 = unsafe { + ((*protocol.as_ptr()).convert_device_node_to_text)( + path.as_ptr(), + // DisplayOnly + r_efi::efi::Boolean::FALSE, + // AllowShortcuts + r_efi::efi::Boolean::FALSE, + ) + }; + + let path = os_string_from_raw(path_ptr) + .ok_or(io::const_error!(io::ErrorKind::InvalidData, "Invalid path"))?; + + if let Some(boot_services) = crate::os::uefi::env::boot_services() { + let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast(); + unsafe { + ((*boot_services.as_ptr()).free_pool)(path_ptr.cast()); + } + } + + Ok(path) + } + + static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + AtomicPtr::new(crate::ptr::null_mut()); + + if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { + if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>( + handle, + device_path_to_text::PROTOCOL_GUID, + ) { + return node_to_text(protocol, path); + } + } + + let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?; + for handle in device_path_to_text_handles { + if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>( + handle, + device_path_to_text::PROTOCOL_GUID, + ) { + LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release); + return node_to_text(protocol, path); + } + } + + Err(io::const_error!(io::ErrorKind::NotFound, "No device path to text protocol found")) +} + /// Gets RuntimeServices. pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> { let system_table: NonNull<r_efi::efi::SystemTable> = @@ -319,6 +373,11 @@ impl<'a> BorrowedDevicePath<'a> { pub(crate) fn to_text(&self) -> io::Result<OsString> { device_path_to_text(self.protocol) } + + #[expect(dead_code)] + pub(crate) const fn iter(&'a self) -> DevicePathIterator<'a> { + DevicePathIterator::new(DevicePathNode::new(self.protocol)) + } } impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> { @@ -330,6 +389,126 @@ impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> { } } +pub(crate) struct DevicePathIterator<'a>(Option<DevicePathNode<'a>>); + +impl<'a> DevicePathIterator<'a> { + const fn new(node: DevicePathNode<'a>) -> Self { + if node.is_end() { Self(None) } else { Self(Some(node)) } + } +} + +impl<'a> Iterator for DevicePathIterator<'a> { + type Item = DevicePathNode<'a>; + + fn next(&mut self) -> Option<Self::Item> { + let cur_node = self.0?; + + let next_node = unsafe { cur_node.next_node() }; + self.0 = if next_node.is_end() { None } else { Some(next_node) }; + + Some(cur_node) + } +} + +#[derive(Copy, Clone)] +pub(crate) struct DevicePathNode<'a> { + protocol: NonNull<r_efi::protocols::device_path::Protocol>, + phantom: PhantomData<&'a r_efi::protocols::device_path::Protocol>, +} + +impl<'a> DevicePathNode<'a> { + pub(crate) const fn new(protocol: NonNull<r_efi::protocols::device_path::Protocol>) -> Self { + Self { protocol, phantom: PhantomData } + } + + pub(crate) const fn length(&self) -> u16 { + let len = unsafe { (*self.protocol.as_ptr()).length }; + u16::from_le_bytes(len) + } + + pub(crate) const fn node_type(&self) -> u8 { + unsafe { (*self.protocol.as_ptr()).r#type } + } + + pub(crate) const fn sub_type(&self) -> u8 { + unsafe { (*self.protocol.as_ptr()).sub_type } + } + + pub(crate) fn data(&self) -> &[u8] { + let length: usize = self.length().into(); + + // Some nodes do not have any special data + if length > 4 { + let raw_ptr: *const u8 = self.protocol.as_ptr().cast(); + let data = unsafe { raw_ptr.add(4) }; + unsafe { crate::slice::from_raw_parts(data, length - 4) } + } else { + &[] + } + } + + pub(crate) const fn is_end(&self) -> bool { + self.node_type() == r_efi::protocols::device_path::TYPE_END + && self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_ENTIRE + } + + #[expect(dead_code)] + pub(crate) const fn is_end_instance(&self) -> bool { + self.node_type() == r_efi::protocols::device_path::TYPE_END + && self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_INSTANCE + } + + pub(crate) unsafe fn next_node(&self) -> Self { + let node = unsafe { + self.protocol + .cast::<u8>() + .add(self.length().into()) + .cast::<r_efi::protocols::device_path::Protocol>() + }; + Self::new(node) + } + + #[expect(dead_code)] + pub(crate) fn to_path(&'a self) -> BorrowedDevicePath<'a> { + BorrowedDevicePath::new(self.protocol) + } + + pub(crate) fn to_text(&self) -> io::Result<OsString> { + device_node_to_text(self.protocol) + } +} + +impl<'a> PartialEq for DevicePathNode<'a> { + fn eq(&self, other: &Self) -> bool { + let self_len = self.length(); + let other_len = other.length(); + + self_len == other_len + && unsafe { + compiler_builtins::mem::memcmp( + self.protocol.as_ptr().cast(), + other.protocol.as_ptr().cast(), + usize::from(self_len), + ) == 0 + } + } +} + +impl<'a> crate::fmt::Debug for DevicePathNode<'a> { + fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { + match self.to_text() { + Ok(p) => p.fmt(f), + Err(_) => f + .debug_struct("DevicePathNode") + .field("type", &self.node_type()) + .field("sub_type", &self.sub_type()) + .field("length", &self.length()) + .field("specific_device_path_data", &self.data()) + .finish(), + } + } +} + pub(crate) struct OwnedProtocol<T> { guid: r_efi::efi::Guid, handle: NonNull<crate::ffi::c_void>, diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 3a238d160cb..91f55fcd32b 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -484,7 +484,12 @@ pub fn current_exe() -> io::Result<PathBuf> { } } -#[cfg(any(target_os = "redox", target_os = "rtems"))] +#[cfg(target_os = "redox")] +pub fn current_exe() -> io::Result<PathBuf> { + crate::fs::read_to_string("/scheme/sys/exe").map(PathBuf::from) +} + +#[cfg(target_os = "rtems")] pub fn current_exe() -> io::Result<PathBuf> { crate::fs::read_to_string("sys:exe").map(PathBuf::from) } diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index 0ea9db211b3..dd41921f263 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -19,8 +19,6 @@ use crate::{fmt, io, ptr}; cfg_if::cfg_if! { if #[cfg(target_os = "fuchsia")] { // fuchsia doesn't have /dev/null - } else if #[cfg(target_os = "redox")] { - const DEV_NULL: &CStr = c"null:"; } else if #[cfg(target_os = "vxworks")] { const DEV_NULL: &CStr = c"/null"; } else { diff --git a/library/std/src/sys/path/unix.rs b/library/std/src/sys/path/unix.rs index 361e99964f1..faa2616a632 100644 --- a/library/std/src/sys/path/unix.rs +++ b/library/std/src/sys/path/unix.rs @@ -62,10 +62,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { } pub(crate) fn is_absolute(path: &Path) -> bool { - if cfg!(target_os = "redox") { - // FIXME: Allow Redox prefixes - path.has_root() || crate::path::has_redox_scheme(path.as_u8_slice()) - } else if cfg!(any(unix, target_os = "hermit", target_os = "wasi")) { + if cfg!(any(unix, target_os = "hermit", target_os = "wasi")) { path.has_root() } else { path.has_root() && path.prefix().is_some() diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 20084a65b8a..7c83c53d2c2 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -67,7 +67,7 @@ impl Std { self } - #[allow(clippy::wrong_self_convention)] + #[expect(clippy::wrong_self_convention)] pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self { self.is_for_mir_opt_tests = is_for_mir_opt_tests; self diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 6fb2996bea6..f82ceb3f7fa 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -583,10 +583,12 @@ Select which editor you would like to set up [default: None]: "; EditorKind::Emacs => &[ "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", + "b5dd299b93dca3ceeb9b335f929293cb3d4bf4977866fbe7ceeac2a8a9f99088", ], EditorKind::Helix => &[ "2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233", "6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040", + "f252dcc30ca85a193a699581e5e929d5bd6c19d40d7a7ade5e257a9517a124a5", ], EditorKind::Vim | EditorKind::VsCode => &[ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", @@ -599,10 +601,12 @@ Select which editor you would like to set up [default: None]: "; "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d", "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", + "e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717", + ], + EditorKind::Zed => &[ + "bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c", + "a5380cf5dd9328731aecc5dfb240d16dac46ed272126b9728006151ef42f5909", ], - EditorKind::Zed => { - &["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"] - } } } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index ba9b1b2fc33..6a6731cafc5 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -1,7 +1,5 @@ //! Attempt to magically identify good tests to run -#![cfg_attr(feature = "build-metrics", allow(unused))] - use std::path::PathBuf; use std::str::FromStr; diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e80f8f9a4b7..01e9abacc6b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3377,7 +3377,7 @@ impl Step for CodegenCranelift { /* let mut prepare_cargo = build_cargo(); prepare_cargo.arg("--").arg("prepare").arg("--download-dir").arg(&download_dir); - #[allow(deprecated)] + #[expect(deprecated)] builder.config.try_run(&mut prepare_cargo.into()).unwrap(); */ @@ -3508,7 +3508,7 @@ impl Step for CodegenGCC { /* let mut prepare_cargo = build_cargo(); prepare_cargo.arg("--").arg("prepare"); - #[allow(deprecated)] + #[expect(deprecated)] builder.config.try_run(&mut prepare_cargo.into()).unwrap(); */ diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 016f09cb2a8..aaf6712102c 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -209,7 +209,7 @@ impl Step for ToolBuild { } } -#[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this. +#[expect(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this. pub fn prepare_tool_cargo( builder: &Builder<'_>, compiler: Compiler, @@ -1024,7 +1024,7 @@ pub struct LibcxxVersionTool { pub target: TargetSelection, } -#[allow(dead_code)] +#[expect(dead_code)] #[derive(Debug, Clone)] pub enum LibcxxVersion { Gnu(usize), diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0b49751f73c..0b6b8513cc3 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1285,7 +1285,6 @@ impl<'a> Builder<'a> { host: TargetSelection, target: TargetSelection, ) -> Compiler { - #![allow(clippy::let_and_return)] let mut resolved_compiler = if self.build.force_use_stage2(stage) { trace!(target: "COMPILER_FOR", ?stage, "force_use_stage2"); self.compiler(2, self.config.build) diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index 9f09dd13f29..179e15e778b 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -1,4 +1,4 @@ -#[allow(clippy::module_inception)] +#[expect(clippy::module_inception)] mod config; pub mod flags; #[cfg(test)] diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 95feb41ffd0..98eff664a5b 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -19,7 +19,7 @@ static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new(); /// `Config::try_run` wrapper for this module to avoid warnings on `try_run`, since we don't have access to a `builder` yet. fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { - #[allow(deprecated)] + #[expect(deprecated)] config.try_run(cmd) } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index fc408437838..8dfd1bbfd60 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -74,7 +74,7 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// Extra `--check-cfg` to add when building the compiler or tools /// (Mode restriction, config name, config values (if any)) -#[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. +#[expect(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[ (None, "bootstrap", None), (Some(Mode::Rustc), "llvm_enzyme", None), diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 7eb9ab96c8a..d07300e21d0 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -125,7 +125,7 @@ impl BootstrapCommand { Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self } } - #[allow(dead_code)] + #[expect(dead_code)] pub fn fail_fast(self) -> Self { Self { failure_behavior: BehaviorOnFailure::Exit, ..self } } @@ -280,7 +280,7 @@ impl CommandOutput { !self.is_success() } - #[allow(dead_code)] + #[expect(dead_code)] pub fn status(&self) -> Option<ExitStatus> { match self.status { CommandStatus::Finished(status) => Some(status), @@ -332,7 +332,6 @@ impl Default for CommandOutput { /// Helper trait to format both Command and BootstrapCommand as a short execution line, /// without all the other details (e.g. environment variables). -#[allow(unused)] pub trait FormatShortCmd { fn format_short_cmd(&self) -> String; } diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 57766fd63fb..885fff9c32c 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -76,7 +76,7 @@ impl BuildMetrics { // Consider all the stats gathered so far as the parent's. if !state.running_steps.is_empty() { - self.collect_stats(&mut *state); + self.collect_stats(&mut state); } state.system_info.refresh_cpu_usage(); @@ -102,7 +102,7 @@ impl BuildMetrics { let mut state = self.state.borrow_mut(); - self.collect_stats(&mut *state); + self.collect_stats(&mut state); let step = state.running_steps.pop().unwrap(); if state.running_steps.is_empty() { @@ -224,6 +224,7 @@ impl BuildMetrics { t!(serde_json::to_writer(&mut file, &json)); } + #[expect(clippy::only_used_in_recursion)] fn prepare_json_step(&self, step: StepMetrics) -> JsonNode { let mut children = Vec::new(); children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child))); diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 45a188fb234..0de8b740227 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -24,6 +24,8 @@ pub struct Job { /// Free additional disk space in the job, by removing unused packages. #[serde(default)] pub free_disk: Option<bool>, + /// Documentation link to a resource that could help people debug this CI job. + pub doc_url: Option<String>, } impl Job { @@ -103,6 +105,8 @@ struct GithubActionsJob { continue_on_error: Option<bool>, #[serde(skip_serializing_if = "Option::is_none")] free_disk: Option<bool>, + #[serde(skip_serializing_if = "Option::is_none")] + doc_url: Option<String>, } /// Skip CI jobs that are not supposed to be executed on the given `channel`. @@ -188,6 +192,7 @@ fn calculate_jobs( env, continue_on_error: job.continue_on_error, free_disk: job.free_disk, + doc_url: job.doc_url, } }) .collect(); diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 1d81d58f893..788f5e7e4f6 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -40,7 +40,7 @@ try-job: dist-i686-msvc"#, fn pr_jobs() { let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true}] + jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=pr "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index 56b9ced2071..ff4d1772f59 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -75,6 +75,7 @@ pr: <<: *job-linux-4c - name: mingw-check-tidy continue_on_error: true + doc_url: https://foo.bar <<: *job-linux-4c # Jobs that run when you perform a try build (@bors try) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index eba55338ff8..d8c3625af28 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -267,11 +267,13 @@ auto: # nightly features to compile, and this job would fail if # executed on beta and stable. only_on_channel: nightly + doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html <<: *job-linux-8c # Tests integration with Rust for Linux. # Builds stage 1 compiler and tries to compile a few RfL examples with it. - name: x86_64-rust-for-linux + doc_url: https://rustc-dev-guide.rust-lang.org/tests/rust-for-linux.html <<: *job-linux-4c - name: x86_64-gnu diff --git a/src/ci/run.sh b/src/ci/run.sh index b874f71832d..823404ea632 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -6,6 +6,10 @@ if [ -n "$CI_JOB_NAME" ]; then echo "[CI_JOB_NAME=$CI_JOB_NAME]" fi +if [ -n "$CI_JOB_DOC_URL" ]; then + echo "[CI_JOB_DOC_URL=$CI_JOB_DOC_URL]" +fi + if [ "$NO_CHANGE_USER" = "" ]; then if [ "$LOCAL_USER_ID" != "" ]; then id -u user &>/dev/null || useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user @@ -54,13 +58,8 @@ if [ "$FORCE_CI_RUSTC" == "" ]; then DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi -if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \ - isCiBranch automation/bors/try; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" - HAS_METRICS=1 -fi - +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-verbose-configure" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules" @@ -266,14 +265,10 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then $SRC/configure --set change-id=99999999 # Save the build metrics before we wipe the directory - if [ "$HAS_METRICS" = 1 ]; then - mv build/metrics.json . - fi + mv build/metrics.json . rm -rf build - if [ "$HAS_METRICS" = 1 ]; then - mkdir build - mv metrics.json build - fi + mkdir build + mv metrics.json build CARGO_INCREMENTAL=0 ../x check fi diff --git a/src/etc/rust_analyzer_eglot.el b/src/etc/rust_analyzer_eglot.el index 7b4309f8e18..6b40371d9af 100644 --- a/src/etc/rust_analyzer_eglot.el +++ b/src/etc/rust_analyzer_eglot.el @@ -8,7 +8,6 @@ "check" "--json-output"]) :linkedProjects ["Cargo.toml" - "src/tools/x/Cargo.toml" "src/bootstrap/Cargo.toml" "src/tools/rust-analyzer/Cargo.toml" "compiler/rustc_codegen_cranelift/Cargo.toml" diff --git a/src/etc/rust_analyzer_helix.toml b/src/etc/rust_analyzer_helix.toml index afddd089eb1..05fc7716a72 100644 --- a/src/etc/rust_analyzer_helix.toml +++ b/src/etc/rust_analyzer_helix.toml @@ -15,7 +15,6 @@ linkedProjects = [ "library/Cargo.toml", "src/bootstrap/Cargo.toml", "src/tools/rust-analyzer/Cargo.toml", - "src/tools/x/Cargo.toml", ] [language-server.rust-analyzer.config.check] diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index b104356d44c..da7d326a512 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -10,7 +10,6 @@ "rust-analyzer.linkedProjects": [ "Cargo.toml", "library/Cargo.toml", - "src/tools/x/Cargo.toml", "src/bootstrap/Cargo.toml", "src/tools/rust-analyzer/Cargo.toml", "compiler/rustc_codegen_cranelift/Cargo.toml", diff --git a/src/etc/rust_analyzer_zed.json b/src/etc/rust_analyzer_zed.json index 469ea050621..abc6ddbc213 100644 --- a/src/etc/rust_analyzer_zed.json +++ b/src/etc/rust_analyzer_zed.json @@ -22,7 +22,6 @@ "linkedProjects": [ "Cargo.toml", "library/Cargo.toml", - "src/tools/x/Cargo.toml", "src/bootstrap/Cargo.toml", "src/tools/rust-analyzer/Cargo.toml", "compiler/rustc_codegen_cranelift/Cargo.toml", diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 707312a97f3..54261079fca 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -201,7 +201,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), - (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), + (Yield(l), Yield(r)) => eq_expr_opt(l.expr(), r.expr()) && l.same_kind(r), + (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), (Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()), (Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()), (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => { @@ -688,7 +689,7 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; - over(&l.attrs, &r.attrs, eq_attr) + over(&l.attrs, &r.attrs, eq_attr) && match (&l.kind, &r.kind) { (BoundPredicate(l), BoundPredicate(r)) => { over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 591aff0defe..ea985866a05 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -65,7 +65,7 @@ impl TestCx<'_> { // FIXME(#41968): Move this check to tidy? if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { - self.fatal("compile-pass tests with expected warnings should be moved to ui/"); + self.fatal("build-pass tests with expected warnings should be moved to ui/"); } } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2e649e688fa..cc3d0cfc717 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -addae0705c7cf5b2f2ed7faeec026c894f497b3d +d9e5539a39192028a7b15ae596a8685017faecee diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr index 5162368b51f..e8babf02163 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: write access through <TAG> at ALLOC[0x0] is forbidden --> RUSTLIB/core/src/mem/mod.rs:LL:CC | -LL | ptr::write(dest, src); - | ^^^^^^^^^^^^^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden +LL | crate::intrinsics::write_via_move(dest, src); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag <TAG> is foreign to the protected tag <TAG> (i.e., it is not a child) diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs index fd2ef9cb1db..034ecde068a 100644 --- a/src/tools/rustfmt/src/chains.rs +++ b/src/tools/rustfmt/src/chains.rs @@ -192,6 +192,7 @@ enum ChainItemKind { StructField(symbol::Ident), TupleField(symbol::Ident, bool), Await, + Yield, Comment(String, CommentPosition), } @@ -203,6 +204,7 @@ impl ChainItemKind { | ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) | ChainItemKind::Await + | ChainItemKind::Yield | ChainItemKind::Comment(..) => false, } } @@ -257,6 +259,10 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } + ast::ExprKind::Yield(ast::YieldKind::Postfix(ref nested)) => { + let span = mk_sp(nested.span.hi(), expr.span.hi()); + (ChainItemKind::Yield, span) + } _ => { return ( ChainItemKind::Parent { @@ -306,6 +312,7 @@ impl Rewrite for ChainItem { rewrite_ident(context, ident) ), ChainItemKind::Await => ".await".to_owned(), + ChainItemKind::Yield => ".yield".to_owned(), ChainItemKind::Comment(ref comment, _) => { rewrite_comment(comment, false, shape, context.config)? } @@ -508,7 +515,8 @@ impl Chain { }), ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(ref subexpr, _) => Some(SubExpr { + | ast::ExprKind::Await(ref subexpr, _) + | ast::ExprKind::Yield(ast::YieldKind::Postfix(ref subexpr)) => Some(SubExpr { expr: Self::convert_try(subexpr, context), is_method_call_receiver: false, }), diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index eff2d2e3ff4..e866f13efc7 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -221,7 +221,7 @@ pub(crate) fn format_expr( Ok(format!("break{id_str}")) } } - ast::ExprKind::Yield(ref opt_expr) => { + ast::ExprKind::Yield(ast::YieldKind::Prefix(ref opt_expr)) => { if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { @@ -243,7 +243,8 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), + | ast::ExprKind::Await(_, _) + | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { wrap_str( diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index fe716c18638..fcd475b1784 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{ self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility, VisibilityKind, }; -use rustc_ast::ptr; +use rustc_ast::{YieldKind, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; @@ -485,7 +485,9 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Index(_, ref expr, _) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), + | ast::ExprKind::Yield(YieldKind::Prefix(Some(ref expr))) => { + is_block_expr(context, expr, repr) + } ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr), // This can only be a string lit ast::ExprKind::Lit(_) => { @@ -515,7 +517,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Tup(..) | ast::ExprKind::Use(..) | ast::ExprKind::Type(..) - | ast::ExprKind::Yield(None) + | ast::ExprKind::Yield(..) | ast::ExprKind::Underscore => false, } } diff --git a/src/tools/rustfmt/tests/target/postfix-yield.rs b/src/tools/rustfmt/tests/target/postfix-yield.rs new file mode 100644 index 00000000000..8ee34ec4312 --- /dev/null +++ b/src/tools/rustfmt/tests/target/postfix-yield.rs @@ -0,0 +1,17 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut coro = pin!( + #[coroutine] + |_: i32| { + let x = 1.yield; + (x + 2).await; + } + ); +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 569d3c67b04..81c55ecaa7a 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -81,7 +81,6 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]), ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]), ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]), - ("src/tools/x", &[], None, &[]), // tidy-alphabetical-end ]; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index bc3519142dd..4078d462f55 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -29,6 +29,7 @@ fn main() { FromStr::from_str(&env::args().nth(4).expect("need concurrency")) .expect("concurrency must be a number"); + let root_manifest = root_path.join("Cargo.toml"); let src_path = root_path.join("src"); let tests_path = root_path.join("tests"); let library_path = root_path.join("library"); @@ -137,6 +138,7 @@ fn main() { check!(edition, &compiler_path); check!(edition, &library_path); + check!(alphabetical, &root_manifest); check!(alphabetical, &src_path); check!(alphabetical, &tests_path); check!(alphabetical, &compiler_path); diff --git a/src/tools/x/Cargo.lock b/src/tools/x/Cargo.lock deleted file mode 100644 index 09e5c750749..00000000000 --- a/src/tools/x/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "x" -version = "0.1.1" diff --git a/tests/codegen/range-loop.rs b/tests/codegen/range-loop.rs new file mode 100644 index 00000000000..b131beb40dd --- /dev/null +++ b/tests/codegen/range-loop.rs @@ -0,0 +1,44 @@ +//@ ignore-std-debug-assertions +//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes + +#![crate_type = "lib"] + +// Ensure that MIR optimizations have cleaned things up enough that the IR we +// emit is good even without running the LLVM optimizations. + +// CHECK-NOT: define + +// CHECK-LABEL: define{{.+}}void @call_for_zero_to_n +#[no_mangle] +pub fn call_for_zero_to_n(n: u32, f: fn(u32)) { + // CHECK: start: + // CHECK-NOT: alloca + // CHECK: %[[IND:.+]] = alloca [4 x i8] + // CHECK-NEXT: %[[ALWAYS_SOME_OPTION:.+]] = alloca + // CHECK-NOT: alloca + // CHECK: store i32 0, ptr %[[IND]], + // CHECK: br label %[[HEAD:.+]] + + // CHECK: [[HEAD]]: + // CHECK: %[[T1:.+]] = load i32, ptr %[[IND]], + // CHECK: %[[NOT_DONE:.+]] = icmp ult i32 %[[T1]], %n + // CHECK: br i1 %[[NOT_DONE]], label %[[BODY:.+]], label %[[BREAK:.+]] + + // CHECK: [[BREAK]]: + // CHECK: ret void + + // CHECK: [[BODY]]: + // CHECK: %[[T2:.+]] = load i32, ptr %[[IND]], + // CHECK: %[[T3:.+]] = add nuw i32 %[[T2]], 1 + // CHECK: store i32 %[[T3]], ptr %[[IND]], + + // CHECK: store i32 %[[T2]] + // CHECK: %[[T4:.+]] = load i32 + // CHECK: call void %f(i32{{.+}}%[[T4]]) + + for i in 0..n { + f(i); + } +} + +// CHECK-NOT: define diff --git a/tests/crashes/125059.rs b/tests/crashes/125059.rs deleted file mode 100644 index 7e9f7414816..00000000000 --- a/tests/crashes/125059.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#125059 -#![feature(deref_patterns)] -#![allow(incomplete_features)] - -fn simple_vec(vec: Vec<u32>) -> u32 { - (|| match Vec::<u32>::new() { - deref!([]) => 100, - _ => 2000, - })() -} - -fn main() {} diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs index 1199ce4e558..62c1d8be1bf 100644 --- a/tests/mir-opt/inline/exponential_runtime.rs +++ b/tests/mir-opt/inline/exponential_runtime.rs @@ -87,10 +87,15 @@ fn main() { // CHECK-LABEL: fn main( // CHECK-NOT: inlined // CHECK: (inlined <() as G>::call) + // CHECK-NOT: inlined // CHECK: (inlined <() as F>::call) + // CHECK-NOT: inlined // CHECK: (inlined <() as E>::call) + // CHECK-NOT: inlined // CHECK: (inlined <() as D>::call) + // CHECK-NOT: inlined // CHECK: (inlined <() as C>::call) + // CHECK-NOT: inlined // CHECK: (inlined <() as B>::call) // CHECK-NOT: inlined <() as G>::call(); diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff index 75fc2ea16e3..f099d763c3d 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff @@ -6,6 +6,7 @@ let _1: (!, !); + let mut _2: fn() -> ! {sleep}; + let mut _7: (); ++ let mut _8: (); + scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { + debug f => _2; + let mut _3: &fn() -> ! {sleep}; @@ -17,6 +18,10 @@ + scope 3 { + debug b => _6; + } ++ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { ++ scope 7 (inlined sleep) { ++ } ++ } + } + scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { + scope 5 (inlined sleep) { diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index 407cb24df67..c33e0810739 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -6,6 +6,7 @@ let _1: (!, !); + let mut _2: fn() -> ! {sleep}; + let mut _8: (); ++ let mut _9: (); + scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { + debug f => _2; + let mut _3: &fn() -> ! {sleep}; @@ -18,6 +19,10 @@ + scope 3 { + debug b => _6; + } ++ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { ++ scope 7 (inlined sleep) { ++ } ++ } + } + scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { + scope 5 (inlined sleep) { diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 1e33e222b27..eb97af1e284 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -55,10 +55,46 @@ + let _26: (); + scope 9 { + } ++ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ } ++ scope 13 (inlined <std::future::Ready<()> as Future>::poll) { ++ let mut _42: (); ++ let mut _43: std::option::Option<()>; ++ let mut _44: &mut std::option::Option<()>; ++ let mut _45: &mut std::future::Ready<()>; ++ let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) { ++ let mut _47: std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _48: &mut &mut std::future::Ready<()>; ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ } ++ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ } ++ } ++ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { ++ } ++ } ++ scope 19 (inlined Option::<()>::take) { ++ let mut _49: std::option::Option<()>; ++ scope 20 (inlined std::mem::replace::<Option<()>>) { ++ scope 21 { ++ } ++ } ++ } ++ scope 22 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _50: isize; ++ let mut _51: !; ++ scope 23 { ++ } ++ } ++ } + } + scope 10 (inlined ready::<()>) { + let mut _41: std::option::Option<()>; + } ++ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) { ++ } + } + } } @@ -113,7 +149,7 @@ + StorageLive(_40); + _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); -+ switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8]; ++ switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5]; } - bb3: { @@ -164,19 +200,16 @@ + _13 = std::future::Ready::<()>(move _41); + StorageDead(_41); + StorageDead(_14); -+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb4, unwind unreachable]; -+ } -+ - bb4: { -- StorageDead(_2); -- return; ++ _12 = move _13; + StorageDead(_13); + _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb5; ++ goto -> bb4; + } + -+ bb5: { + bb4: { +- StorageDead(_2); +- return; + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -185,10 +218,7 @@ + _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); -+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable]; -+ } -+ -+ bb6: { ++ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); + StorageLive(_23); @@ -197,21 +227,36 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); -+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb7, unwind unreachable]; -+ } -+ -+ bb7: { -+ StorageDead(_22); -+ StorageDead(_19); -+ _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb10, 1: bb9, otherwise: bb8]; ++ StorageLive(_45); ++ StorageLive(_46); ++ StorageLive(_49); ++ StorageLive(_51); ++ StorageLive(_42); ++ StorageLive(_43); ++ StorageLive(_44); ++ _46 = &mut _19; ++ StorageLive(_47); ++ StorageLive(_48); ++ _48 = &mut (_19.0: &mut std::future::Ready<()>); ++ _45 = copy (_19.0: &mut std::future::Ready<()>); ++ StorageDead(_48); ++ _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 }; ++ StorageDead(_47); ++ _44 = &mut ((*_45).0: std::option::Option<()>); ++ _49 = Option::<()>::None; ++ _43 = copy ((*_45).0: std::option::Option<()>); ++ ((*_45).0: std::option::Option<()>) = copy _49; ++ StorageDead(_44); ++ StorageLive(_50); ++ _50 = discriminant(_43); ++ switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5]; + } + -+ bb8: { ++ bb5: { + unreachable; + } + -+ bb9: { ++ bb6: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -229,7 +274,7 @@ + goto -> bb2; + } + -+ bb10: { ++ bb7: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -240,17 +285,17 @@ + StorageDead(_17); + StorageDead(_12); + _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable]; ++ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; + } + -+ bb11: { ++ bb8: { + _7 = Poll::<()>::Ready(move _30); + _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_40)) = 1; + goto -> bb2; + } + -+ bb12: { ++ bb9: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -259,11 +304,31 @@ + _31 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb5; ++ goto -> bb4; + } + -+ bb13: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb13, unwind unreachable]; ++ bb10: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb10, unwind unreachable]; ++ } ++ ++ bb11: { ++ _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ } ++ ++ bb12: { ++ _42 = move ((_43 as Some).0: ()); ++ StorageDead(_50); ++ StorageDead(_43); ++ _18 = Poll::<()>::Ready(move _42); ++ StorageDead(_42); ++ StorageDead(_51); ++ StorageDead(_49); ++ StorageDead(_46); ++ StorageDead(_45); ++ StorageDead(_22); ++ StorageDead(_19); ++ _25 = discriminant(_18); ++ switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5]; } } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index b1840beb3ef..eb757e09114 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -57,10 +57,46 @@ + let _26: (); + scope 9 { + } ++ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ } ++ scope 13 (inlined <std::future::Ready<()> as Future>::poll) { ++ let mut _44: (); ++ let mut _45: std::option::Option<()>; ++ let mut _46: &mut std::option::Option<()>; ++ let mut _47: &mut std::future::Ready<()>; ++ let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) { ++ let mut _49: std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _50: &mut &mut std::future::Ready<()>; ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ } ++ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ } ++ } ++ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { ++ } ++ } ++ scope 19 (inlined Option::<()>::take) { ++ let mut _51: std::option::Option<()>; ++ scope 20 (inlined std::mem::replace::<Option<()>>) { ++ scope 21 { ++ } ++ } ++ } ++ scope 22 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _52: isize; ++ let mut _53: !; ++ scope 23 { ++ } ++ } ++ } + } + scope 10 (inlined ready::<()>) { + let mut _43: std::option::Option<()>; + } ++ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) { ++ } + } + } } @@ -117,7 +153,7 @@ + StorageLive(_42); + _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); -+ switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10]; ++ switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7]; } - bb3: { @@ -181,21 +217,16 @@ + _13 = std::future::Ready::<()>(move _43); + StorageDead(_43); + StorageDead(_14); -+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb6, unwind: bb17]; - } - -- bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; -+ bb6: { ++ _12 = move _13; + StorageDead(_13); + _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb7; ++ goto -> bb6; } -- bb6 (cleanup): { -- resume; -+ bb7: { +- bb5 (cleanup): { +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; ++ bb6: { + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -204,10 +235,7 @@ + _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); -+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15]; -+ } -+ -+ bb8: { ++ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); + StorageLive(_23); @@ -216,21 +244,38 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); -+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb9, unwind: bb14]; -+ } -+ -+ bb9: { -+ StorageDead(_22); -+ StorageDead(_19); -+ _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb12, 1: bb11, otherwise: bb10]; -+ } -+ -+ bb10: { ++ StorageLive(_47); ++ StorageLive(_48); ++ StorageLive(_51); ++ StorageLive(_53); ++ StorageLive(_44); ++ StorageLive(_45); ++ StorageLive(_46); ++ _48 = &mut _19; ++ StorageLive(_49); ++ StorageLive(_50); ++ _50 = &mut (_19.0: &mut std::future::Ready<()>); ++ _47 = copy (_19.0: &mut std::future::Ready<()>); ++ StorageDead(_50); ++ _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 }; ++ StorageDead(_49); ++ _46 = &mut ((*_47).0: std::option::Option<()>); ++ _51 = Option::<()>::None; ++ _45 = copy ((*_47).0: std::option::Option<()>); ++ ((*_47).0: std::option::Option<()>) = copy _51; ++ StorageDead(_46); ++ StorageLive(_52); ++ _52 = discriminant(_45); ++ switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7]; + } + +- bb6 (cleanup): { +- resume; ++ bb7: { + unreachable; + } + -+ bb11: { ++ bb8: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -248,7 +293,7 @@ + goto -> bb4; + } + -+ bb12: { ++ bb9: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -259,54 +304,35 @@ + StorageDead(_17); + StorageDead(_12); + _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19]; ++ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; + } + -+ bb13: { ++ bb10: { + _7 = Poll::<()>::Ready(move _30); + _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_40)) = 1; + goto -> bb4; + } + -+ bb14 (cleanup): { ++ bb11 (cleanup): { + StorageDead(_22); + StorageDead(_19); + StorageDead(_23); -+ goto -> bb16; -+ } -+ -+ bb15 (cleanup): { -+ StorageDead(_20); -+ StorageDead(_19); -+ goto -> bb16; -+ } -+ -+ bb16 (cleanup): { + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); -+ goto -> bb18; -+ } -+ -+ bb17 (cleanup): { -+ StorageDead(_13); -+ goto -> bb18; -+ } -+ -+ bb18 (cleanup): { + StorageDead(_12); + _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)]; ++ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; + } + -+ bb19 (cleanup): { ++ bb12 (cleanup): { + _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_42)) = 2; + goto -> bb2; + } + -+ bb20: { ++ bb13: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -315,15 +341,35 @@ + _31 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb7; ++ goto -> bb6; + } + -+ bb21: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb21, unwind: bb2]; ++ bb14: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb14, unwind: bb2]; + } + -+ bb22: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb22, unwind: bb2]; ++ bb15: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb15, unwind: bb2]; ++ } ++ ++ bb16: { ++ _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ } ++ ++ bb17: { ++ _44 = move ((_45 as Some).0: ()); ++ StorageDead(_52); ++ StorageDead(_45); ++ _18 = Poll::<()>::Ready(move _44); ++ StorageDead(_44); ++ StorageDead(_53); ++ StorageDead(_51); ++ StorageDead(_48); ++ StorageDead(_47); ++ StorageDead(_22); ++ StorageDead(_19); ++ _25 = discriminant(_18); ++ switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7]; } } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index be69bbf10e7..1f9c464d633 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -26,6 +26,18 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _12: usize; scope 6 { debug old => _11; + scope 8 (inlined <usize as Step>::forward_unchecked) { + debug start => _11; + debug n => const 1_usize; + scope 9 (inlined core::num::<impl usize>::unchecked_add) { + debug self => _11; + debug rhs => const 1_usize; + scope 10 (inlined core::ub_checks::check_language_ub) { + scope 11 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) { debug self => _6; @@ -50,7 +62,6 @@ fn int_range(_1: usize, _2: usize) -> () { bb1: { StorageLive(_13); _5 = &mut _4; - StorageLive(_11); StorageLive(_10); StorageLive(_6); _6 = &(_4.0: usize); @@ -70,7 +81,6 @@ fn int_range(_1: usize, _2: usize) -> () { StorageDead(_7); StorageDead(_6); StorageDead(_10); - StorageDead(_11); StorageDead(_13); StorageDead(_4); return; @@ -81,20 +91,16 @@ fn int_range(_1: usize, _2: usize) -> () { StorageDead(_6); _11 = copy (_4.0: usize); StorageLive(_12); - _12 = <usize as Step>::forward_unchecked(copy _11, const 1_usize) -> [return: bb4, unwind continue]; - } - - bb4: { + _12 = AddUnchecked(copy _11, const 1_usize); (_4.0: usize) = move _12; StorageDead(_12); _13 = Option::<usize>::Some(copy _11); StorageDead(_10); - StorageDead(_11); _14 = copy ((_13 as Some).0: usize); - _15 = opaque::<usize>(move _14) -> [return: bb5, unwind continue]; + _15 = opaque::<usize>(move _14) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { StorageDead(_13); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir index ed494f6e74c..958a06bcd34 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -6,10 +6,6 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { let mut _0: u32; scope 1 (inlined std::mem::replace::<u32>) { scope 2 { - scope 4 (inlined std::ptr::write::<u32>) { - } - } - scope 3 (inlined std::ptr::read::<u32>) { } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir index ed494f6e74c..958a06bcd34 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -6,10 +6,6 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { let mut _0: u32; scope 1 (inlined std::mem::replace::<u32>) { scope 2 { - scope 4 (inlined std::ptr::write::<u32>) { - } - } - scope 3 (inlined std::ptr::read::<u32>) { } } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 5d33c33d73f..0aa37203c1b 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -23,6 +23,14 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let _7: u32; let mut _8: u32; scope 6 { + scope 8 (inlined <u32 as Step>::forward_unchecked) { + scope 9 (inlined core::num::<impl u32>::unchecked_add) { + scope 10 (inlined core::ub_checks::check_language_ub) { + scope 11 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) { let mut _5: u32; @@ -41,7 +49,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb1: { StorageLive(_9); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = copy _4; @@ -52,7 +59,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { StorageDead(_6); - StorageDead(_7); StorageDead(_9); StorageDead(_4); drop(_3) -> [return: bb3, unwind unreachable]; @@ -65,24 +71,20 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb4: { _7 = copy _4; StorageLive(_8); - _8 = <u32 as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable]; - } - - bb5: { + _8 = AddUnchecked(copy _7, const 1_u32); _4 = move _8; StorageDead(_8); _9 = Option::<u32>::Some(copy _7); StorageDead(_6); - StorageDead(_7); _10 = copy ((_9 as Some).0: u32); StorageLive(_11); _11 = &_3; StorageLive(_12); _12 = (copy _10,); - _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb6, unwind unreachable]; + _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind unreachable]; } - bb6: { + bb5: { StorageDead(_12); StorageDead(_11); StorageDead(_9); diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index ded30a15520..699d8bc8fea 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -23,6 +23,14 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let _7: u32; let mut _8: u32; scope 6 { + scope 8 (inlined <u32 as Step>::forward_unchecked) { + scope 9 (inlined core::num::<impl u32>::unchecked_add) { + scope 10 (inlined core::ub_checks::check_language_ub) { + scope 11 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) { let mut _5: u32; @@ -41,7 +49,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb1: { StorageLive(_9); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = copy _4; @@ -52,7 +59,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { StorageDead(_6); - StorageDead(_7); StorageDead(_9); StorageDead(_4); drop(_3) -> [return: bb3, unwind continue]; @@ -65,35 +71,31 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb4: { _7 = copy _4; StorageLive(_8); - _8 = <u32 as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb7]; - } - - bb5: { + _8 = AddUnchecked(copy _7, const 1_u32); _4 = move _8; StorageDead(_8); _9 = Option::<u32>::Some(copy _7); StorageDead(_6); - StorageDead(_7); _10 = copy ((_9 as Some).0: u32); StorageLive(_11); _11 = &_3; StorageLive(_12); _12 = (copy _10,); - _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb6, unwind: bb7]; + _13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb6]; } - bb6: { + bb5: { StorageDead(_12); StorageDead(_11); StorageDead(_9); goto -> bb1; } - bb7 (cleanup): { - drop(_3) -> [return: bb8, unwind terminate(cleanup)]; + bb6 (cleanup): { + drop(_3) -> [return: bb7, unwind terminate(cleanup)]; } - bb8 (cleanup): { + bb7 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir index 2621ec67531..f3033d4a2fa 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir @@ -9,6 +9,14 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { let _5: u32; let mut _6: u32; scope 3 { + scope 5 (inlined <u32 as Step>::forward_unchecked) { + scope 6 (inlined core::num::<impl u32>::unchecked_add) { + scope 7 (inlined core::ub_checks::check_language_ub) { + scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) { let mut _2: u32; @@ -18,7 +26,6 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { } bb0: { - StorageLive(_5); StorageLive(_4); StorageLive(_2); _2 = copy ((*_1).0: u32); @@ -32,25 +39,21 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { bb1: { _0 = const Option::<u32>::None; - goto -> bb4; + goto -> bb3; } bb2: { _5 = copy ((*_1).0: u32); StorageLive(_6); - _6 = <u32 as Step>::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind unreachable]; - } - - bb3: { + _6 = AddUnchecked(copy _5, const 1_u32); ((*_1).0: u32) = move _6; StorageDead(_6); _0 = Option::<u32>::Some(copy _5); - goto -> bb4; + goto -> bb3; } - bb4: { + bb3: { StorageDead(_4); - StorageDead(_5); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir index 338fb4b9523..f3033d4a2fa 100644 --- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir @@ -9,6 +9,14 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { let _5: u32; let mut _6: u32; scope 3 { + scope 5 (inlined <u32 as Step>::forward_unchecked) { + scope 6 (inlined core::num::<impl u32>::unchecked_add) { + scope 7 (inlined core::ub_checks::check_language_ub) { + scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) { let mut _2: u32; @@ -18,7 +26,6 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { } bb0: { - StorageLive(_5); StorageLive(_4); StorageLive(_2); _2 = copy ((*_1).0: u32); @@ -32,25 +39,21 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> { bb1: { _0 = const Option::<u32>::None; - goto -> bb4; + goto -> bb3; } bb2: { _5 = copy ((*_1).0: u32); StorageLive(_6); - _6 = <u32 as Step>::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind continue]; - } - - bb3: { + _6 = AddUnchecked(copy _5, const 1_u32); ((*_1).0: u32) = move _6; StorageDead(_6); _0 = Option::<u32>::Some(copy _5); - goto -> bb4; + goto -> bb3; } - bb4: { + bb3: { StorageDead(_4); - StorageDead(_5); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index 151783969dd..f8d11df5185 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -28,6 +28,14 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _7: usize; let mut _8: usize; scope 7 { + scope 9 (inlined <usize as Step>::forward_unchecked) { + scope 10 (inlined core::num::<impl usize>::unchecked_add) { + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) { let mut _5: usize; @@ -47,7 +55,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb1: { StorageLive(_9); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = copy _4; @@ -58,7 +65,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); - StorageDead(_7); StorageDead(_9); StorageDead(_4); drop(_2) -> [return: bb3, unwind unreachable]; @@ -71,30 +77,26 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = copy _4; StorageLive(_8); - _8 = <usize as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable]; - } - - bb5: { + _8 = AddUnchecked(copy _7, const 1_usize); _4 = move _8; StorageDead(_8); _9 = Option::<usize>::Some(copy _7); StorageDead(_6); - StorageDead(_7); _10 = copy ((_9 as Some).0: usize); _11 = Lt(copy _10, copy _3); - assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind unreachable]; + assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind unreachable]; } - bb6: { + bb5: { _12 = &(*_1)[_10]; StorageLive(_13); _13 = &_2; StorageLive(_14); _14 = (copy _10, copy _12); - _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind unreachable]; + _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { StorageDead(_14); StorageDead(_13); StorageDead(_9); diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 006329dc20d..2c249197894 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -28,6 +28,14 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let _7: usize; let mut _8: usize; scope 7 { + scope 9 (inlined <usize as Step>::forward_unchecked) { + scope 10 (inlined core::num::<impl usize>::unchecked_add) { + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) { let mut _5: usize; @@ -47,7 +55,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb1: { StorageLive(_9); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = copy _4; @@ -58,7 +65,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); - StorageDead(_7); StorageDead(_9); StorageDead(_4); drop(_2) -> [return: bb3, unwind continue]; @@ -71,41 +77,37 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = copy _4; StorageLive(_8); - _8 = <usize as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb8]; - } - - bb5: { + _8 = AddUnchecked(copy _7, const 1_usize); _4 = move _8; StorageDead(_8); _9 = Option::<usize>::Some(copy _7); StorageDead(_6); - StorageDead(_7); _10 = copy ((_9 as Some).0: usize); _11 = Lt(copy _10, copy _3); - assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind: bb8]; + assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind: bb7]; } - bb6: { + bb5: { _12 = &(*_1)[_10]; StorageLive(_13); _13 = &_2; StorageLive(_14); _14 = (copy _10, copy _12); - _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind: bb8]; + _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind: bb7]; } - bb7: { + bb6: { StorageDead(_14); StorageDead(_13); StorageDead(_9); goto -> bb1; } - bb8 (cleanup): { - drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + bb7 (cleanup): { + drop(_2) -> [return: bb8, unwind terminate(cleanup)]; } - bb9 (cleanup): { + bb8 (cleanup): { resume; } } diff --git a/tests/pretty/postfix-yield.rs b/tests/pretty/postfix-yield.rs new file mode 100644 index 00000000000..f76e8142ae8 --- /dev/null +++ b/tests/pretty/postfix-yield.rs @@ -0,0 +1,15 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 +//@ pp-exact + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut gn = gen { yield 1; 2.yield; (1 + 2).yield; }; + + let mut coro = + pin!(#[coroutine] |_: i32| { let x = 1.yield; (x + 2).yield; }); +} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap.rs b/tests/ui/cast/ptr-to-trait-obj-wrap.rs index 6f9f6bddb99..9809ea80f95 100644 --- a/tests/ui/cast/ptr-to-trait-obj-wrap.rs +++ b/tests/ui/cast/ptr-to-trait-obj-wrap.rs @@ -2,7 +2,6 @@ // work. Note that the metadata doesn't change when a DST is wrapped in a // structure, so these casts *are* fine. // -// `unwrap` and `unwrap_nested` currently don't work due to a compiler limitation. //@ check-pass trait A {} diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs new file mode 100644 index 00000000000..ff843138c8c --- /dev/null +++ b/tests/ui/coroutine/postfix-yield.rs @@ -0,0 +1,34 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. + +//@ run-pass +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + // generators (i.e. yield doesn't return anything useful) + let mut gn = gen { + yield 1; + 2.yield; + }; + + assert_eq!(gn.next(), Some(1)); + assert_eq!(gn.next(), Some(2)); + assert_eq!(gn.next(), None); + + //coroutines (i.e. yield returns something useful) + let mut coro = pin!( + #[coroutine] + |_: i32| { + let x = 1.yield; + (x + 2).yield; + } + ); + + assert_eq!(coro.as_mut().resume(0), CoroutineState::Yielded(1)); + assert_eq!(coro.as_mut().resume(2), CoroutineState::Yielded(4)); + assert_eq!(coro.as_mut().resume(3), CoroutineState::Complete(())); +} diff --git a/tests/ui/lint/unused/unused-field-in-pat-field.rs b/tests/ui/lint/unused/unused-field-in-pat-field.rs new file mode 100644 index 00000000000..34959a1023f --- /dev/null +++ b/tests/ui/lint/unused/unused-field-in-pat-field.rs @@ -0,0 +1,21 @@ +//@ check-pass + +// Ensure we collect lint levels from pat fields in structs. + +#![deny(unused_variables)] + +pub struct Foo { + bar: u32, + baz: u32, +} + +pub fn test(foo: Foo) { + let Foo { + #[allow(unused_variables)] + bar, + #[allow(unused_variables)] + baz, + } = foo; +} + +fn main() {} diff --git a/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs new file mode 100644 index 00000000000..e1a37b9c65f --- /dev/null +++ b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs @@ -0,0 +1,15 @@ +//@ check-pass +//! Regression test for ICE in `rustc_hir_typeck::expr_use_visitor` on nesting a slice pattern +//! inside a deref pattern inside a closure: rust-lang/rust#125059 + +#![feature(deref_patterns)] +#![allow(incomplete_features, unused)] + +fn simple_vec(vec: Vec<u32>) -> u32 { + (|| match Vec::<u32>::new() { + deref!([]) => 100, + _ => 2000, + })() +} + +fn main() {} diff --git a/triagebot.toml b/triagebot.toml index 84aae8a5179..68595122769 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1115,7 +1115,6 @@ compiler = [ "@wesleywiser", ] libs = [ - "@cuviper", "@Mark-Simulacrum", "@Amanieu", "@Noratrieb", |
