diff options
246 files changed, 2450 insertions, 1319 deletions
diff --git a/Cargo.lock b/Cargo.lock index c2e635b4cfe..3d4a1bf6a78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "anstyle-svg" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc03a770ef506fe1396c0e476120ac0e6523cf14b74218dd5f18cd6833326fa9" +checksum = "26b9ec8c976eada1b0f9747a3d7cc4eae3bef10613e443746e7487f26c872fde" dependencies = [ "anstyle", "anstyle-lossy", @@ -1333,6 +1333,12 @@ dependencies = [ ] [[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + +[[package]] name = "flate2" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3556,7 +3562,7 @@ dependencies = [ "ar_archive_writer", "bitflags", "bstr", - "cc", + "find-msvc-tools", "itertools", "libc", "object 0.37.3", @@ -4760,7 +4766,7 @@ dependencies = [ name = "rustc_windows_rc" version = "0.0.0" dependencies = [ - "cc", + "find-msvc-tools", ] [[package]] diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5f4bfd9df48..0910e8ef4b3 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1736,9 +1736,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { // `BoringNoLocation` constraints can point to user-written code, but are less // specific, and are not used for relations that would make sense to blame. ConstraintCategory::BoringNoLocation => 6, - // Do not blame internal constraints. - ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 7, - ConstraintCategory::Internal => 8, + // Do not blame internal constraints if we can avoid it. Never blame + // the `'region: 'static` constraints introduced by placeholder outlives. + ConstraintCategory::Internal => 7, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8, }; debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 19cbcd139aa..606d3d95d9e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -505,6 +505,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let mut constraints = Default::default(); let mut liveness_constraints = LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body))); + let mut deferred_closure_requirements = Default::default(); // Don't try to add borrow_region facts for the promoted MIR as they refer // to the wrong locations. @@ -512,6 +513,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { mem::swap(this.polonius_facts, polonius_facts); mem::swap(&mut this.constraints.outlives_constraints, &mut constraints); mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints); + mem::swap(this.deferred_closure_requirements, &mut deferred_closure_requirements); }; swap_constraints(self); @@ -536,6 +538,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } self.constraints.outlives_constraints.push(constraint) } + + // If there are nested bodies in promoteds, we also need to update their + // location to something in the actual body, not the promoted. + // + // We don't update the constraint categories of the resulting constraints + // as returns in nested bodies are a proper return, even if that nested body + // is in a promoted. + for (closure_def_id, args, _locations) in deferred_closure_requirements { + self.deferred_closure_requirements.push((closure_def_id, args, locations)); + } + // If the region is live at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region // at the location provided as an argument to this method diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 51089e5a1d3..82c59d5a3a2 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -63,8 +63,8 @@ pub fn inject( if sess.is_test_crate() { let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) { - (PanicStrategy::Abort, true) => PanicStrategy::Abort, - (PanicStrategy::Abort, false) => { + (PanicStrategy::Abort | PanicStrategy::ImmediateAbort, true) => panic_strategy, + (PanicStrategy::Abort | PanicStrategy::ImmediateAbort, false) => { if panic_strategy == platform_panic_strategy { // Silently allow compiling with panic=abort on these platforms, // but with old behavior (abort if a test fails). @@ -287,10 +287,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> { let ecx = &cx.ext_cx; let test_ident = Ident::new(sym::test, sp); - let runner_name = match cx.panic_strategy { - PanicStrategy::Unwind => "test_main_static", - PanicStrategy::Abort => "test_main_static_abort", - }; + let runner_name = + if cx.panic_strategy.unwinds() { "test_main_static" } else { "test_main_static_abort" }; // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| { diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index e9d72e457a0..e8672f49580 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -15,9 +15,9 @@ use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::Symbol; +use rustc_target::spec::RelocModel; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; -use rustc_target::spec::{PanicStrategy, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -101,7 +101,7 @@ pub fn compile_codegen_unit( // Instantiate monomorphizations without filling out definitions yet... let context = new_context(tcx); - if tcx.sess.panic_strategy() == PanicStrategy::Unwind { + if tcx.sess.panic_strategy().unwinds() { context.add_command_line_option("-fexceptions"); context.add_driver_option("-fexceptions"); } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 84fa56cf903..a915f5d6418 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -29,7 +29,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; -use rustc_target::spec::PanicStrategy; #[cfg(feature = "master")] use crate::abi::FnAbiGccExt; @@ -1334,7 +1333,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( _catch_func: RValue<'gcc>, dest: PlaceRef<'tcx, RValue<'gcc>>, ) { - if bx.sess().panic_strategy() == PanicStrategy::Abort { + if !bx.sess().panic_strategy().unwinds() { bx.call(bx.type_void(), None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 573c51a9539..dcf6b945497 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -407,13 +407,16 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); // For non-naked functions, set branch protection attributes on aarch64. - if let Some(BranchProtection { bti, pac_ret }) = + if let Some(BranchProtection { bti, pac_ret, gcs }) = cx.sess().opts.unstable_opts.branch_protection { assert!(cx.sess().target.arch == "aarch64"); if bti { to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); } + if gcs { + to_add.push(llvm::CreateAttrString(cx.llcx, "guarded-control-stack")); + } if let Some(PacRet { leaf, pc, key }) = pac_ret { if pc { to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr")); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 4a8ea11a3a8..057f525c76f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -370,7 +370,8 @@ pub(crate) unsafe fn create_module<'ll>( ); } - if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { + if let Some(BranchProtection { bti, pac_ret, gcs }) = sess.opts.unstable_opts.branch_protection + { if sess.target.arch == "aarch64" { llvm::add_module_flag_u32( llmod, @@ -403,6 +404,12 @@ pub(crate) unsafe fn create_module<'ll>( "sign-return-address-with-bkey", u32::from(pac_opts.key == PAuthKey::B), ); + llvm::add_module_flag_u32( + llmod, + llvm::ModuleFlagMergeBehavior::Min, + "guarded-control-stack", + gcs.into(), + ); } else { bug!( "branch-protection used on non-AArch64 target; \ diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e7f4a357048..50398a32142 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -18,7 +18,6 @@ use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; use rustc_target::callconv::PassMode; -use rustc_target::spec::PanicStrategy; use tracing::debug; use crate::abi::FnAbiLlvmExt; @@ -674,7 +673,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>( catch_func: &'ll Value, dest: PlaceRef<'tcx, &'ll Value>, ) { - if bx.sess().panic_strategy() == PanicStrategy::Abort { + if !bx.sess().panic_strategy().unwinds() { let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); bx.call(try_func_ty, None, None, try_func, &[data], None, None); // Return 0 unconditionally from the intrinsic call; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 45c5c9aa551..3b920168e06 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -106,7 +106,7 @@ unsafe fn configure_llvm(sess: &Session) { if sess.target.os == "emscripten" && !sess.opts.unstable_opts.emscripten_wasm_eh - && sess.panic_strategy() == PanicStrategy::Unwind + && sess.panic_strategy().unwinds() { add("-enable-emscripten-cxx-exceptions", false); } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 5462163f4ff..9c5a3d839ce 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,9 +8,7 @@ edition = "2024" ar_archive_writer = "0.5" bitflags = "2.4.1" bstr = "1.11.3" -# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_windows_rc`. -cc = "=1.2.16" +find-msvc-tools = "0.1.2" itertools = "0.12" pathdiff = "0.2.0" regex = "1.4" diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 48b01ea2df1..d6c304c1b14 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -9,7 +9,7 @@ use std::path::{Path, PathBuf}; use std::process::{Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; -use cc::windows_registry; +use find_msvc_tools; use itertools::Itertools; use regex::Regex; use rustc_arena::TypedArena; @@ -47,8 +47,8 @@ use rustc_span::Symbol; use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, - LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, - SanitizerSet, SplitDebuginfo, + LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, RelocModel, RelroLevel, SanitizerSet, + SplitDebuginfo, }; use tracing::{debug, info, warn}; @@ -877,9 +877,9 @@ fn link_natively( // All Microsoft `link.exe` linking ror codes are // four digit numbers in the range 1000 to 9999 inclusive if is_msvc_link_exe && (code < 1000 || code > 9999) { - let is_vs_installed = windows_registry::find_vs_version().is_ok(); + let is_vs_installed = find_msvc_tools::find_vs_version().is_ok(); let has_linker = - windows_registry::find_tool(&sess.target.arch, "link.exe").is_some(); + find_msvc_tools::find_tool(&sess.target.arch, "link.exe").is_some(); sess.dcx().emit_note(errors::LinkExeUnexpectedError); @@ -2512,10 +2512,10 @@ fn add_order_independent_options( if sess.target.os == "emscripten" { cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh { "-fwasm-exceptions" - } else if sess.panic_strategy() == PanicStrategy::Abort { - "-sDISABLE_EXCEPTION_CATCHING=1" - } else { + } else if sess.panic_strategy().unwinds() { "-sDISABLE_EXCEPTION_CATCHING=0" + } else { + "-sDISABLE_EXCEPTION_CATCHING=1" }); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a2efd420a32..624ab1b5084 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -4,7 +4,7 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::{env, io, iter, mem, str}; -use cc::windows_registry; +use find_msvc_tools; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::{ find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, @@ -53,7 +53,7 @@ pub(crate) fn get_linker<'a>( self_contained: bool, target_cpu: &'a str, ) -> Box<dyn Linker + 'a> { - let msvc_tool = windows_registry::find_tool(&sess.target.arch, "link.exe"); + let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe"); // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle @@ -117,7 +117,6 @@ pub(crate) fn get_linker<'a>( if sess.target.is_like_msvc && let Some(ref tool) = msvc_tool { - cmd.args(tool.args()); for (k, v) in tool.env() { if k == "PATH" { new_path.extend(env::split_paths(v)); @@ -845,6 +844,11 @@ impl<'a> Linker for GccLinker<'a> { self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); } self.link_arg("--dynamic-list").link_arg(path); + } else if self.sess.target.is_like_wasm { + self.link_arg("--no-export-dynamic"); + for (sym, _) in symbols { + self.link_arg("--export").link_arg(sym); + } } else { // Write an LD version script let res: io::Result<()> = try { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index d2b275ad20a..70d796cda11 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, PResult}; use rustc_macros::{Decodable, Encodable}; use rustc_session::parse::ParseSess; -use rustc_span::{Ident, Span, Symbol}; +use rustc_span::{Ident, Span, Symbol, sym}; use crate::errors; @@ -69,15 +69,15 @@ impl MetaVarExpr { } let mut iter = args.iter(); - let rslt = match ident.as_str() { - "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?, - "count" => parse_count(&mut iter, psess, ident.span)?, - "ignore" => { + let rslt = match ident.name { + sym::concat => parse_concat(&mut iter, psess, outer_span, ident.span)?, + sym::count => parse_count(&mut iter, psess, ident.span)?, + sym::ignore => { eat_dollar(&mut iter, psess, ident.span)?; MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?) } - "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), - "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), + sym::index => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), + sym::len => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), _ => { let err = errors::MveUnrecognizedExpr { span: ident.span, @@ -119,14 +119,13 @@ fn check_trailing_tokens<'psess>( } // `None` for max indicates the arg count must be exact, `Some` indicates a range is accepted. - let (min_or_exact_args, max_args) = match ident.as_str() { - "concat" => panic!("concat takes unlimited tokens but didn't eat them all"), - "ignore" => (1, None), + let (min_or_exact_args, max_args) = match ident.name { + sym::concat => panic!("concat takes unlimited tokens but didn't eat them all"), + sym::ignore => (1, None), // 1 or 2 args - "count" => (1, Some(2)), + sym::count => (1, Some(2)), // 0 or 1 arg - "index" => (0, Some(1)), - "len" => (0, Some(1)), + sym::index | sym::len => (0, Some(1)), other => unreachable!("unknown MVEs should be rejected earlier (got `{other}`)"), }; diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 6a3f1f62c91..dddd62a4945 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -375,6 +375,19 @@ fn transcribe_metavar<'tx>( return Ok(()); }; + let MatchedSingle(pnr) = cur_matched else { + // We were unable to descend far enough. This is an error. + return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident })); + }; + + transcribe_pnr(tscx, sp, pnr) +} + +fn transcribe_pnr<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + mut sp: Span, + pnr: &ParseNtResult, +) -> PResult<'tx, ()> { // We wrap the tokens in invisible delimiters, unless they are already wrapped // in invisible delimiters with the same `MetaVarKind`. Because some proc // macros can't handle multiple layers of invisible delimiters of the same @@ -404,33 +417,33 @@ fn transcribe_metavar<'tx>( ) }; - let tt = match cur_matched { - MatchedSingle(ParseNtResult::Tt(tt)) => { + let tt = match pnr { + ParseNtResult::Tt(tt) => { // `tt`s are emitted into the output stream directly as "raw tokens", // without wrapping them into groups. Other variables are emitted into // the output stream as groups with `Delimiter::Invisible` to maintain // parsing priorities. maybe_use_metavar_location(tscx.psess, &tscx.stack, sp, tt, &mut tscx.marker) } - MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { + ParseNtResult::Ident(ident, is_raw) => { tscx.marker.mark_span(&mut sp); with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); let kind = token::NtIdent(*ident, *is_raw); TokenTree::token_alone(kind, sp) } - MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => { + ParseNtResult::Lifetime(ident, is_raw) => { tscx.marker.mark_span(&mut sp); with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } - MatchedSingle(ParseNtResult::Item(item)) => { + ParseNtResult::Item(item) => { mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item)) } - MatchedSingle(ParseNtResult::Block(block)) => { + ParseNtResult::Block(block) => { mk_delimited(block.span, MetaVarKind::Block, TokenStream::from_ast(block)) } - MatchedSingle(ParseNtResult::Stmt(stmt)) => { + ParseNtResult::Stmt(stmt) => { let stream = if let StmtKind::Empty = stmt.kind { // FIXME: Properly collect tokens for empty statements. TokenStream::token_alone(token::Semi, stmt.span) @@ -439,10 +452,10 @@ fn transcribe_metavar<'tx>( }; mk_delimited(stmt.span, MetaVarKind::Stmt, stream) } - MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => { + ParseNtResult::Pat(pat, pat_kind) => { mk_delimited(pat.span, MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) } - MatchedSingle(ParseNtResult::Expr(expr, kind)) => { + ParseNtResult::Expr(expr, kind) => { let (can_begin_literal_maybe_minus, can_begin_string_literal) = match &expr.kind { ExprKind::Lit(_) => (true, true), ExprKind::Unary(UnOp::Neg, e) if matches!(&e.kind, ExprKind::Lit(_)) => { @@ -460,14 +473,14 @@ fn transcribe_metavar<'tx>( TokenStream::from_ast(expr), ) } - MatchedSingle(ParseNtResult::Literal(lit)) => { + ParseNtResult::Literal(lit) => { mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit)) } - MatchedSingle(ParseNtResult::Ty(ty)) => { + ParseNtResult::Ty(ty) => { let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); mk_delimited(ty.span, MetaVarKind::Ty { is_path }, TokenStream::from_ast(ty)) } - MatchedSingle(ParseNtResult::Meta(attr_item)) => { + ParseNtResult::Meta(attr_item) => { let has_meta_form = attr_item.meta_kind().is_some(); mk_delimited( attr_item.span(), @@ -475,16 +488,12 @@ fn transcribe_metavar<'tx>( TokenStream::from_ast(attr_item), ) } - MatchedSingle(ParseNtResult::Path(path)) => { + ParseNtResult::Path(path) => { mk_delimited(path.span, MetaVarKind::Path, TokenStream::from_ast(path)) } - MatchedSingle(ParseNtResult::Vis(vis)) => { + ParseNtResult::Vis(vis) => { mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis)) } - MatchedSeq(..) => { - // We were unable to descend far enough. This is an error. - return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident })); - } }; tscx.result.push(tt); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index aa2d27ab809..bc3448be582 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -64,83 +64,159 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi // it's usually worth updating that intrinsic's documentation // to note that it's safe to call, since // safe extern fns are otherwise unprecedented. - sym::abort + + // tidy-alphabetical-start + | sym::abort + | sym::add_with_overflow + | sym::aggregate_raw_ptr + | sym::align_of | sym::assert_inhabited - | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid + | sym::assert_zero_valid + | sym::autodiff + | sym::bitreverse + | sym::black_box | sym::box_new | sym::breakpoint - | sym::size_of - | sym::align_of - | sym::needs_drop + | sym::bswap | sym::caller_location - | sym::add_with_overflow - | sym::sub_with_overflow - | sym::mul_with_overflow | sym::carrying_mul_add - | sym::wrapping_add - | sym::wrapping_sub - | sym::wrapping_mul - | sym::saturating_add - | sym::saturating_sub - | sym::rotate_left - | sym::rotate_right - | sym::ctpop + | sym::ceilf16 + | sym::ceilf32 + | sym::ceilf64 + | sym::ceilf128 + | sym::cold_path + | sym::const_eval_select + | sym::contract_check_ensures + | sym::contract_check_requires + | sym::contract_checks + | sym::copysignf16 + | sym::copysignf32 + | sym::copysignf64 + | sym::copysignf128 + | sym::cosf16 + | sym::cosf32 + | sym::cosf64 + | sym::cosf128 | sym::ctlz + | sym::ctpop | sym::cttz - | sym::bswap - | sym::bitreverse - | sym::three_way_compare | sym::discriminant_value - | sym::type_id - | sym::type_id_eq - | sym::select_unpredictable - | sym::cold_path - | sym::ptr_guaranteed_cmp - | sym::minnumf16 - | sym::minnumf32 - | sym::minnumf64 - | sym::minnumf128 - | sym::minimumf16 - | sym::minimumf32 - | sym::minimumf64 - | sym::minimumf128 - | sym::maxnumf16 - | sym::maxnumf32 - | sym::maxnumf64 - | sym::maxnumf128 + | sym::exp2f16 + | sym::exp2f32 + | sym::exp2f64 + | sym::exp2f128 + | sym::expf16 + | sym::expf32 + | sym::expf64 + | sym::expf128 + | sym::fabsf16 + | sym::fabsf32 + | sym::fabsf64 + | sym::fabsf128 + | sym::fadd_algebraic + | sym::fdiv_algebraic + | sym::floorf16 + | sym::floorf32 + | sym::floorf64 + | sym::floorf128 + | sym::fmaf16 + | sym::fmaf32 + | sym::fmaf64 + | sym::fmaf128 + | sym::fmul_algebraic + | sym::fmuladdf16 + | sym::fmuladdf32 + | sym::fmuladdf64 + | sym::fmuladdf128 + | sym::forget + | sym::frem_algebraic + | sym::fsub_algebraic + | sym::is_val_statically_known + | sym::log2f16 + | sym::log2f32 + | sym::log2f64 + | sym::log2f128 + | sym::log10f16 + | sym::log10f32 + | sym::log10f64 + | sym::log10f128 + | sym::logf16 + | sym::logf32 + | sym::logf64 + | sym::logf128 | sym::maximumf16 | sym::maximumf32 | sym::maximumf64 | sym::maximumf128 - | sym::rustc_peek - | sym::type_name - | sym::forget - | sym::black_box - | sym::variant_count - | sym::is_val_statically_known + | sym::maxnumf16 + | sym::maxnumf32 + | sym::maxnumf64 + | sym::maxnumf128 + | sym::minimumf16 + | sym::minimumf32 + | sym::minimumf64 + | sym::minimumf128 + | sym::minnumf16 + | sym::minnumf32 + | sym::minnumf64 + | sym::minnumf128 + | sym::mul_with_overflow + | sym::needs_drop + | sym::powf16 + | sym::powf32 + | sym::powf64 + | sym::powf128 + | sym::powif16 + | sym::powif32 + | sym::powif64 + | sym::powif128 + | sym::prefetch_read_data + | sym::prefetch_read_instruction + | sym::prefetch_write_data + | sym::prefetch_write_instruction + | sym::ptr_guaranteed_cmp | sym::ptr_mask - | sym::aggregate_raw_ptr | sym::ptr_metadata - | sym::ub_checks - | sym::contract_checks - | sym::contract_check_requires - | sym::contract_check_ensures - | sym::fadd_algebraic - | sym::fsub_algebraic - | sym::fmul_algebraic - | sym::fdiv_algebraic - | sym::frem_algebraic + | sym::rotate_left + | sym::rotate_right | sym::round_ties_even_f16 | sym::round_ties_even_f32 | sym::round_ties_even_f64 | sym::round_ties_even_f128 - | sym::autodiff - | sym::prefetch_read_data - | sym::prefetch_write_data - | sym::prefetch_read_instruction - | sym::prefetch_write_instruction - | sym::const_eval_select => hir::Safety::Safe, + | sym::roundf16 + | sym::roundf32 + | sym::roundf64 + | sym::roundf128 + | sym::rustc_peek + | sym::saturating_add + | sym::saturating_sub + | sym::select_unpredictable + | sym::sinf16 + | sym::sinf32 + | sym::sinf64 + | sym::sinf128 + | sym::size_of + | sym::sqrtf16 + | sym::sqrtf32 + | sym::sqrtf64 + | sym::sqrtf128 + | sym::sub_with_overflow + | sym::three_way_compare + | sym::truncf16 + | sym::truncf32 + | sym::truncf64 + | sym::truncf128 + | sym::type_id + | sym::type_id_eq + | sym::type_name + | sym::ub_checks + | sym::variant_count + | sym::wrapping_add + | sym::wrapping_mul + | sym::wrapping_sub + // tidy-alphabetical-end + => hir::Safety::Safe, _ => hir::Safety::Unsafe, }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f735c0a4160..46accb76a18 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -47,7 +47,7 @@ You can read more about trait objects in the Trait Objects section of the Refere https://doc.rust-lang.org/reference/types.html#trait-objects"; fn is_number(text: &str) -> bool { - text.chars().all(|c: char| c.is_digit(10)) + text.chars().all(|c: char| c.is_ascii_digit()) } /// Information about the expected type at the top level of type checking a pattern. @@ -262,8 +262,9 @@ enum InheritedRefMatchRule { /// pattern matches a given type: /// - If the underlying type is not a reference, a reference pattern may eat the inherited reference; /// - If the underlying type is a reference, a reference pattern matches if it can eat either one - /// of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the - /// underlying type is `&mut` or the inherited reference is `&mut`. + /// of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the + /// underlying type is `&mut` or the inherited reference is `&mut`. + /// /// If `false`, a reference pattern is only matched against the underlying type. /// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and /// `ref_pat_eat_one_layer_2024_structural` feature gates. @@ -1069,7 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if !self.tcx.features().mut_ref() { feature_err( - &self.tcx.sess, + self.tcx.sess, sym::mut_ref, pat.span.until(ident.span), "binding cannot be both mutable and by-reference", @@ -1487,31 +1488,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_def_id: Option<hir::def_id::DefId>, ident: Ident, ) -> bool { - match opt_def_id { - Some(def_id) => match self.tcx.hir_get_if_local(def_id) { - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Const(_, _, _, body_id), - .. - })) => match self.tcx.hir_node(body_id.hir_id) { - hir::Node::Expr(expr) => { - if hir::is_range_literal(expr) { - let span = self.tcx.hir_span(body_id.hir_id); - if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) { - e.span_suggestion_verbose( - ident.span, - "you may want to move the range into the match block", - snip, - Applicability::MachineApplicable, - ); - return true; - } - } - } - _ => (), - }, - _ => (), - }, - _ => (), + if let Some(def_id) = opt_def_id + && let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(_, _, _, body_id), + .. + })) = self.tcx.hir_get_if_local(def_id) + && let hir::Node::Expr(expr) = self.tcx.hir_node(body_id.hir_id) + && hir::is_range_literal(expr) + { + let span = self.tcx.hir_span(body_id.hir_id); + if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) { + e.span_suggestion_verbose( + ident.span, + "you may want to move the range into the match block", + snip, + Applicability::MachineApplicable, + ); + return true; + } } false } @@ -1529,7 +1523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = self.tcx.hir_res_span(pat_res) { e.span_label(span, format!("{} defined here", res.descr())); - if let [hir::PathSegment { ident, .. }] = &*segments { + if let [hir::PathSegment { ident, .. }] = segments { e.span_label( pat_span, format!( @@ -1557,17 +1551,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => (None, None), }; - let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) { + let is_range = matches!( + type_def_id.and_then(|id| self.tcx.as_lang_item(id)), Some( LangItem::Range - | LangItem::RangeFrom - | LangItem::RangeTo - | LangItem::RangeFull - | LangItem::RangeInclusiveStruct - | LangItem::RangeToInclusive, - ) => true, - _ => false, - }; + | LangItem::RangeFrom + | LangItem::RangeTo + | LangItem::RangeFull + | LangItem::RangeInclusiveStruct + | LangItem::RangeToInclusive, + ) + ); if is_range { if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) { let msg = "constants only support matching by type, \ diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 6f6666f8c76..1f5c5e74d97 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -47,7 +47,7 @@ interface_out_dir_error = failed to find or create the directory specified by `--out-dir` interface_proc_macro_crate_panic_abort = - building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic + building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 6cefe887530..761a5c80918 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -42,7 +42,6 @@ use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, }; -use rustc_target::spec::PanicStrategy; use rustc_trait_selection::{solve, traits}; use tracing::{info, instrument}; @@ -282,7 +281,7 @@ fn configure_and_expand( feature_err(sess, sym::export_stable, DUMMY_SP, "`sdylib` crate type is unstable").emit(); } - if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { + if is_proc_macro_crate && !sess.panic_strategy().unwinds() { sess.dcx().emit_warn(errors::ProcMacroCratePanicAbort); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 7730bddc0f1..800f5efee41 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -772,7 +772,8 @@ fn test_unstable_options_tracking_hash() { branch_protection, Some(BranchProtection { bti: true, - pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B }) + pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B }), + gcs: true, }) ); tracked!(codegen_backend, Some("abc".to_string())); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index c29ab569f47..f6790f7ed1e 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -599,14 +599,16 @@ impl Cursor<'_> { if potential_closing.is_none() { // a less fortunate recovery if all else fails which finds any dashes preceded by whitespace // on a standalone line. Might be wrong. + let mut base_index = 0; while let Some(closing) = rest.find("---") { let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1); if rest[preceding_chars_start..closing].chars().all(is_horizontal_whitespace) { // candidate found - potential_closing = Some(closing); + potential_closing = Some(closing + base_index); break; } else { rest = &rest[closing + 3..]; + base_index += closing + 3; } } } diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 0dfd1b13df5..ad93c745381 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -10,8 +10,7 @@ libc = "0.2.73" [build-dependencies] # tidy-alphabetical-start -# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_codegen_ssa` and `rustc_windows_rc`. +# `cc` updates often break things, so we pin it here. cc = "=1.2.16" # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index e104be2c466..e624bfc5b8b 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -98,6 +98,13 @@ metadata_full_metadata_not_found = metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait +metadata_incompatible_with_immediate_abort = + the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort` + +metadata_incompatible_with_immediate_abort_core = + the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort` + .help = consider building the standard library from source with `cargo build -Zbuild-std` + metadata_incompatible_panic_in_drop_strategy = the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 9e23da88f5e..7650acbd292 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1027,6 +1027,10 @@ impl CStore { let name = match desired_strategy { PanicStrategy::Unwind => sym::panic_unwind, PanicStrategy::Abort => sym::panic_abort, + PanicStrategy::ImmediateAbort => { + // Immediate-aborting panics don't use a runtime. + return; + } }; info!("panic runtime not found -- loading {}", name); diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index fb9c2e23b71..8054a48d37a 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -61,11 +61,13 @@ use rustc_session::config::CrateType; use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; use rustc_span::sym; +use rustc_target::spec::PanicStrategy; use tracing::info; use crate::creader::CStore; use crate::errors::{ - BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, + BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, + IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired, NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired, TwoPanicRuntimes, }; @@ -402,15 +404,43 @@ fn activate_injected_dep( /// there's only going to be one panic runtime in the output. fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) { let sess = &tcx.sess; + let list: Vec<_> = list + .iter_enumerated() + .filter_map( + |(cnum, linkage)| if *linkage == Linkage::NotLinked { None } else { Some(cnum) }, + ) + .collect(); if list.is_empty() { return; } - let mut panic_runtime = None; - for (cnum, linkage) in list.iter_enumerated() { - if let Linkage::NotLinked = *linkage { - continue; + let desired_strategy = sess.panic_strategy(); + + // If we are panic=immediate-abort, make sure everything in the dependency tree has also been + // compiled with immediate-abort. + if list + .iter() + .any(|cnum| tcx.required_panic_strategy(*cnum) == Some(PanicStrategy::ImmediateAbort)) + { + let mut invalid_crates = Vec::new(); + for cnum in list.iter().copied() { + if tcx.required_panic_strategy(cnum) != Some(PanicStrategy::ImmediateAbort) { + invalid_crates.push(cnum); + // If core is incompatible, it's very likely that we'd emit an error for every + // sysroot crate, so instead of doing that emit a single fatal error that suggests + // using build-std. + if tcx.crate_name(cnum) == sym::core { + sess.dcx().emit_fatal(IncompatibleWithImmediateAbortCore); + } + } } + for cnum in invalid_crates { + sess.dcx() + .emit_err(IncompatibleWithImmediateAbort { crate_name: tcx.crate_name(cnum) }); + } + } + let mut panic_runtime = None; + for cnum in list.iter().copied() { if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { let prev_name = tcx.crate_name(prev); @@ -430,8 +460,6 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) { // only one, but we perform validation here that all the panic strategy // compilation modes for the whole DAG are valid. if let Some((runtime_cnum, found_strategy)) = panic_runtime { - let desired_strategy = sess.panic_strategy(); - // First up, validate that our selected panic runtime is indeed exactly // our same strategy. if found_strategy != desired_strategy { @@ -445,10 +473,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) { // strategy. If the dep isn't linked, we ignore it, and if our strategy // is abort then it's compatible with everything. Otherwise all crates' // panic strategy must match our own. - for (cnum, linkage) in list.iter_enumerated() { - if let Linkage::NotLinked = *linkage { - continue; - } + for cnum in list.iter().copied() { if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) { continue; } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index e5a4fd48353..abfd078f746 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -76,6 +76,16 @@ pub struct RequiredPanicStrategy { } #[derive(Diagnostic)] +#[diag(metadata_incompatible_with_immediate_abort)] +pub struct IncompatibleWithImmediateAbort { + pub crate_name: Symbol, +} + +#[derive(Diagnostic)] +#[diag(metadata_incompatible_with_immediate_abort_core)] +pub struct IncompatibleWithImmediateAbortCore; + +#[derive(Diagnostic)] #[diag(metadata_incompatible_panic_in_drop_strategy)] pub struct IncompatiblePanicInDropStrategy { pub crate_name: Symbol, diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 93264f02cc2..a0e4c288c4a 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -98,5 +98,6 @@ pub fn required(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { lang_item != LangItem::EhPersonality && lang_item != LangItem::EhCatchTypeinfo } PanicStrategy::Unwind => true, + PanicStrategy::ImmediateAbort => false, } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c477e65f5d6..47b45c58b9f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -16,7 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use rustc_target::callconv::FnAbi; -use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi}; +use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; @@ -1198,7 +1198,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) // // Note that this is true regardless ABI specified on the function -- a `extern "C-unwind"` // function defined in Rust is also required to abort. - if tcx.sess.panic_strategy() == PanicStrategy::Abort && !tcx.is_foreign_item(did) { + if !tcx.sess.panic_strategy().unwinds() && !tcx.is_foreign_item(did) { return false; } @@ -1206,7 +1206,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) // // This is not part of `codegen_fn_attrs` as it can differ between crates // and therefore cannot be computed in core. - if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort + if !tcx.sess.opts.unstable_opts.panic_in_drop.unwinds() && tcx.is_lang_item(did, LangItem::DropInPlace) { return false; @@ -1245,7 +1245,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) | RiscvInterruptS | RustInvalid | Unadjusted => false, - Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind, + Rust | RustCall | RustCold => tcx.sess.panic_strategy().unwinds(), } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4f039381e50..a4422abc688 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1368,7 +1368,6 @@ impl<'tcx> Ty<'tcx> { /// 2229 drop reorder migration analysis. #[inline] pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { - assert!(!self.has_non_region_infer()); // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1381,6 +1380,16 @@ impl<'tcx> Ty<'tcx> { _ => self, }; + // FIXME + // We should be canonicalizing, or else moving this to a method of inference + // context, or *something* like that, + // but for now just avoid passing inference variables + // to queries that can't cope with them. + // Instead, conservatively return "true" (may change drop order). + if query_ty.has_infer() { + return true; + } + // This doesn't depend on regions, so try to minimize distinct // query keys used. let erased = tcx.normalize_erasing_regions(typing_env, query_ty); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index c1cd2788348..c5cd06f170c 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -86,7 +86,6 @@ use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::source_map::dummy_spanned; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::PanicStrategy; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; @@ -1149,7 +1148,7 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::Typing fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // Nothing can unwind when landing pads are off. - if tcx.sess.panic_strategy() == PanicStrategy::Abort { + if !tcx.sess.panic_strategy().unwinds() { return false; } diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index abbff1c48dd..7c66783548e 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -101,12 +101,15 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { } fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrategy> { + let local_strategy = tcx.sess.panic_strategy(); + if tcx.is_panic_runtime(LOCAL_CRATE) { - return Some(tcx.sess.panic_strategy()); + return Some(local_strategy); } - if tcx.sess.panic_strategy() == PanicStrategy::Abort { - return Some(PanicStrategy::Abort); + match local_strategy { + PanicStrategy::Abort | PanicStrategy::ImmediateAbort => return Some(local_strategy), + _ => {} } for def_id in tcx.hir_body_owners() { diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 5b6d7ffb511..b53c1f6d202 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -1,7 +1,6 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_target::spec::PanicStrategy; use tracing::debug; use crate::patch::MirPatch; @@ -13,7 +12,7 @@ pub(super) struct RemoveNoopLandingPads; impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.panic_strategy() != PanicStrategy::Abort + sess.panic_strategy().unwinds() } fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 795cb2b2cfe..ebb6a93b1dd 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -29,7 +29,8 @@ use rustc_span::{ SourceFileHashAlgorithm, Symbol, sym, }; use rustc_target::spec::{ - FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple, + FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo, + Target, TargetTuple, }; use tracing::debug; @@ -1620,6 +1621,7 @@ pub struct PacRet { pub struct BranchProtection { pub bti: bool, pub pac_ret: Option<PacRet>, + pub gcs: bool, } pub(crate) const fn default_lib_output() -> CrateType { @@ -2799,6 +2801,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M } } + if !unstable_options_enabled && cg.panic == Some(PanicStrategy::ImmediateAbort) { + early_dcx.early_fatal( + "`-Cpanic=immediate-abort` requires `-Zunstable-options` and a nightly compiler", + ) + } + let crate_name = matches.opt_str("crate-name"); let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); // Parse any `-l` flags, which link to native libraries. diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 7e970461ab7..f3d91ce4a5d 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -125,7 +125,9 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { None | Some(_), ) => disallow(cfg, "-Z sanitizer=cfi"), (sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"), - (sym::panic, Some(sym::abort | sym::unwind)) => disallow(cfg, "-C panic"), + (sym::panic, Some(sym::abort | sym::unwind | sym::immediate_abort)) => { + disallow(cfg, "-C panic") + } (sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"), (sym::unix, None) | (sym::windows, None) @@ -203,7 +205,14 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_none!(sym::overflow_checks); } + // We insert a cfg for the name of session's panic strategy. + // Since the ImmediateAbort strategy is new, it also sets cfg(panic="abort"), so that code + // which is trying to detect whether unwinding is enabled by checking for cfg(panic="abort") + // does not need to be updated. ins_sym!(sym::panic, sess.panic_strategy().desc_symbol()); + if sess.panic_strategy() == PanicStrategy::ImmediateAbort { + ins_sym!(sym::panic, PanicStrategy::Abort.desc_symbol()); + } // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 69facde6936..b2cc169f12c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -802,7 +802,7 @@ mod desc { pub(crate) const parse_threads: &str = parse_number; pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`"; pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`"; - pub(crate) const parse_panic_strategy: &str = "either `unwind` or `abort`"; + pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`"; pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; @@ -866,7 +866,7 @@ mod desc { pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; pub(crate) const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; - pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`"; + pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set)"; pub(crate) const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; pub(crate) const parse_remap_path_scope: &str = @@ -1165,6 +1165,7 @@ pub mod parse { match v { Some("unwind") => *slot = Some(PanicStrategy::Unwind), Some("abort") => *slot = Some(PanicStrategy::Abort), + Some("immediate-abort") => *slot = Some(PanicStrategy::ImmediateAbort), _ => return false, } true @@ -1174,6 +1175,7 @@ pub mod parse { match v { Some("unwind") => *slot = PanicStrategy::Unwind, Some("abort") => *slot = PanicStrategy::Abort, + Some("immediate-abort") => *slot = PanicStrategy::ImmediateAbort, _ => return false, } true @@ -1903,6 +1905,7 @@ pub mod parse { Some(pac) => pac.pc = true, _ => return false, }, + "gcs" => slot.gcs = true, _ => return false, }; } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d0dd2cdac0c..25b46241c52 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -777,9 +777,11 @@ impl Session { // Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>` // value, if it is provided, or disable them, if not. self.target.requires_uwtable - || self.opts.cg.force_unwind_tables.unwrap_or( - self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable, - ) + || self + .opts + .cg + .force_unwind_tables + .unwrap_or(self.panic_strategy().unwinds() || self.target.default_uwtable) } /// Returns the number of query threads that should be used for this @@ -1229,7 +1231,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } // KCFI requires panic=abort - if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy() != PanicStrategy::Abort { + if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy().unwinds() { sess.dcx().emit_err(errors::SanitizerKcfiRequiresPanicAbort); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a6ae58f87dc..4e48c96afd6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1196,6 +1196,7 @@ symbols! { if_let_rescope, if_while_or_patterns, ignore, + immediate_abort: "immediate-abort", impl_header_lifetime_elision, impl_lint_pass, impl_trait_in_assoc_type, diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index be15da7329d..6ab8597a4ec 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -21,6 +21,7 @@ pub(crate) mod linux_uclibc; pub(crate) mod linux_wasm; pub(crate) mod lynxos178; pub(crate) mod managarm_mlibc; +pub(crate) mod motor; pub(crate) mod msvc; pub(crate) mod netbsd; pub(crate) mod nto_qnx; diff --git a/compiler/rustc_target/src/spec/base/motor.rs b/compiler/rustc_target/src/spec/base/motor.rs new file mode 100644 index 00000000000..18485b2cef2 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/motor.rs @@ -0,0 +1,34 @@ +use crate::spec::{ + Cc, FramePointer, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions, +}; + +pub(crate) fn opts() -> TargetOptions { + let pre_link_args = TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::No, Lld::No), + &[ + "-e", + "motor_start", + "--no-undefined", + "--error-unresolved-symbols", + "--no-undefined-version", + "-u", + "__rust_abort", + ], + ); + TargetOptions { + os: "motor".into(), + executables: true, + // TLS is false below because if true, the compiler assumes + // we handle TLS at the ELF loading level, which we don't. + // We use "OS level" TLS (see thread/local.rs in stdlib). + has_thread_local: false, + frame_pointer: FramePointer::NonLeaf, + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), + main_needs_argc_argv: true, + panic_strategy: PanicStrategy::Abort, + pre_link_args, + stack_probes: StackProbeType::Inline, + supports_stack_protector: true, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/base/wasm.rs b/compiler/rustc_target/src/spec/base/wasm.rs index 88e7af5e669..7ede45766ea 100644 --- a/compiler/rustc_target/src/spec/base/wasm.rs +++ b/compiler/rustc_target/src/spec/base/wasm.rs @@ -81,11 +81,6 @@ pub(crate) fn options() -> TargetOptions { // threaded model which will legalize atomics to normal operations. singlethread: true, - // Symbol visibility takes care of this for the WebAssembly. - // Additionally the only known linker, LLD, doesn't support the script - // arguments just yet - limit_rdylib_exports: false, - // we use the LLD shipped with the Rust toolchain by default linker: Some("rust-lld".into()), linker_flavor: LinkerFlavor::WasmLld(Cc::No), diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f705af52bd8..4a82a8bd888 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -834,6 +834,7 @@ crate::target_spec_enum! { pub enum PanicStrategy { Unwind = "unwind", Abort = "abort", + ImmediateAbort = "immediate-abort", } parse_error_type = "panic strategy"; @@ -852,8 +853,13 @@ impl PanicStrategy { match *self { PanicStrategy::Unwind => sym::unwind, PanicStrategy::Abort => sym::abort, + PanicStrategy::ImmediateAbort => sym::immediate_abort, } } + + pub fn unwinds(self) -> bool { + matches!(self, PanicStrategy::Unwind) + } } crate::target_spec_enum! { @@ -1642,6 +1648,7 @@ supported_targets! { ("aarch64-unknown-hermit", aarch64_unknown_hermit), ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit), ("x86_64-unknown-hermit", x86_64_unknown_hermit), + ("x86_64-unknown-motor", x86_64_unknown_motor), ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_motor.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_motor.rs new file mode 100644 index 00000000000..0fd43357a76 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_motor.rs @@ -0,0 +1,38 @@ +use crate::spec::{ + CodeModel, LinkSelfContainedDefault, LldFlavor, RelocModel, RelroLevel, Target, base, +}; + +pub(crate) fn target() -> Target { + let mut base = base::motor::opts(); + base.cpu = "x86-64".into(); + base.max_atomic_width = Some(64); + base.code_model = Some(CodeModel::Small); + + // We want fully static relocatable binaries. It was surprisingly + // difficult to make it happen reliably, especially various + // linker-related options below. Mostly trial and error. + base.position_independent_executables = true; + base.relro_level = RelroLevel::Full; + base.static_position_independent_executables = true; + base.relocation_model = RelocModel::Pic; + base.lld_flavor_json = LldFlavor::Ld; + base.link_self_contained = LinkSelfContainedDefault::True; + base.dynamic_linking = false; + base.crt_static_default = true; + base.crt_static_respected = true; + + Target { + llvm_target: "x86_64-unknown-none-elf".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Motor OS".into()), + tier: Some(3), + host_tools: None, + std: None, + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/compiler/rustc_thread_pool/src/latch.rs b/compiler/rustc_thread_pool/src/latch.rs index 18d654d9f78..58dabaf35c0 100644 --- a/compiler/rustc_thread_pool/src/latch.rs +++ b/compiler/rustc_thread_pool/src/latch.rs @@ -388,13 +388,17 @@ impl Latch for CountLatch { #[inline] unsafe fn set(this: *const Self) { if unsafe { (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 } { - // NOTE: Once we call `set` on the internal `latch`, + // SAFETY: Once we call `set` on the internal `latch`, // the target may proceed and invalidate `this`! match unsafe { &(*this).kind } { CountLatchKind::Stealing { latch, registry, worker_index } => { let registry = Arc::clone(registry); + let worker_index = *worker_index; + // SAFETY: We don't use any references from `this` after this call. if unsafe { CoreLatch::set(latch) } { - registry.notify_worker_latch_is_set(*worker_index); + // We **must not** access any part of `this` anymore, which + // is why we read and shadowed these fields beforehand. + registry.notify_worker_latch_is_set(worker_index); } } CountLatchKind::Blocking { latch } => unsafe { LockLatch::set(latch) }, diff --git a/compiler/rustc_windows_rc/Cargo.toml b/compiler/rustc_windows_rc/Cargo.toml index 080acd35c38..13f716897fa 100644 --- a/compiler/rustc_windows_rc/Cargo.toml +++ b/compiler/rustc_windows_rc/Cargo.toml @@ -5,7 +5,5 @@ edition = "2024" [dependencies] #tidy-alphabetical-start -# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version -# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_codegen_ssa`. -cc = "=1.2.16" +find-msvc-tools = "0.1.2" #tidy-alphabetical-end diff --git a/compiler/rustc_windows_rc/src/lib.rs b/compiler/rustc_windows_rc/src/lib.rs index 5e95557501e..15afaf7b94b 100644 --- a/compiler/rustc_windows_rc/src/lib.rs +++ b/compiler/rustc_windows_rc/src/lib.rs @@ -2,9 +2,7 @@ //! //! Uses values from the `CFG_VERSION` and `CFG_RELEASE` environment variables //! to set the product and file version information in the Windows resource file. -use std::{env, ffi, fs, path, process}; - -use cc::windows_registry; +use std::{env, fs, path, process}; /// The template for the Windows resource file. const RESOURCE_TEMPLATE: &str = include_str!("../rustc.rc.in"); @@ -38,7 +36,10 @@ pub fn compile_windows_resource_file( let resource_compiler = if let Ok(path) = env::var("RUSTC_WINDOWS_RC") { path.into() } else { - find_resource_compiler(&env::var("CARGO_CFG_TARGET_ARCH").unwrap()).expect("found rc.exe") + find_msvc_tools::find_tool(&env::var("CARGO_CFG_TARGET_ARCH").unwrap(), "rc.exe") + .expect("found rc.exe") + .path() + .to_owned() }; let rc_path = resources_dir.join(file_stem.with_extension("rc")); @@ -134,28 +135,3 @@ fn parse_version(version: &str) -> Option<ResourceVersion> { Some(ResourceVersion { major, minor, patch, build: 0 }) } } - -/// Find the Windows SDK resource compiler `rc.exe` for the given architecture or target triple. -/// Returns `None` if the tool could not be found. -fn find_resource_compiler(arch_or_target: &str) -> Option<path::PathBuf> { - find_windows_sdk_tool(arch_or_target, "rc.exe") -} - -/// Find a Windows SDK tool for the given architecture or target triple. -/// Returns `None` if the tool could not be found. -fn find_windows_sdk_tool(arch_or_target: &str, tool_name: &str) -> Option<path::PathBuf> { - // windows_registry::find_tool can only find MSVC tools, not Windows SDK tools, but - // cc does include the Windows SDK tools in the PATH environment of MSVC tools. - - let msvc_linker = windows_registry::find_tool(arch_or_target, "link.exe")?; - let path = &msvc_linker.env().iter().find(|(k, _)| k == "PATH")?.1; - find_tool_in_path(tool_name, path) -} - -/// Find a tool in the directories in a given PATH-like string. -fn find_tool_in_path<P: AsRef<ffi::OsStr>>(tool_name: &str, path: P) -> Option<path::PathBuf> { - env::split_paths(path.as_ref()).find_map(|p| { - let tool_path = p.join(tool_name); - if tool_path.try_exists().unwrap_or(false) { Some(tool_path) } else { None } - }) -} diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 9ba7c5bd28a..fb1f8c86dbf 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -22,8 +22,6 @@ compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"] -# Make panics and failed asserts immediately abort without formatting any message -panic_immediate_abort = ["core/panic_immediate_abort"] # Choose algorithms that are optimized for binary size instead of runtime performance optimize_for_size = ["core/optimize_for_size"] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 76630a746dd..65c8206e9d4 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -408,12 +408,12 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { } } - #[cfg(not(feature = "panic_immediate_abort"))] + #[cfg(not(panic = "immediate-abort"))] { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) } - #[cfg(feature = "panic_immediate_abort")] + #[cfg(panic = "immediate-abort")] ct_error(layout) } diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index b0027e964e4..b7c153b825d 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -23,7 +23,7 @@ mod tests; // ensure that the code generation related to these panics is minimal as there's // only one location which panics rather than a bunch throughout the module. #[cfg(not(no_global_oom_handling))] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] fn capacity_overflow() -> ! { panic!("capacity overflow"); diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index fcb466778a3..aed3357afbf 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -480,8 +480,6 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::rc::Rc; /// /// let mut five = Rc::<u32>::new_uninit(); @@ -572,7 +570,6 @@ impl<T> Rc<T> { /// /// ``` /// #![feature(allocator_api)] - /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; /// @@ -1014,8 +1011,6 @@ impl<T> Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::rc::Rc; /// /// let mut values = Rc::<[u32]>::new_uninit_slice(3); @@ -1181,8 +1176,6 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::rc::Rc; /// /// let mut five = Rc::<u32>::new_uninit(); @@ -1218,8 +1211,6 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::rc::Rc; /// /// let mut values = Rc::<[u32]>::new_uninit_slice(3); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 32396cccb8f..a466b74944c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -480,8 +480,6 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::sync::Arc; /// /// let mut five = Arc::<u32>::new_uninit(); @@ -586,7 +584,6 @@ impl<T> Arc<T> { /// /// ``` /// #![feature(allocator_api)] - /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; /// @@ -1156,8 +1153,6 @@ impl<T> Arc<[T]> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::sync::Arc; /// /// let mut values = Arc::<[u32]>::new_uninit_slice(3); @@ -1326,8 +1321,6 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::sync::Arc; /// /// let mut five = Arc::<u32>::new_uninit(); @@ -1364,8 +1357,6 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> { /// # Examples /// /// ``` - /// #![feature(get_mut_unchecked)] - /// /// use std::sync::Arc; /// /// let mut values = Arc::<[u32]>::new_uninit_slice(3); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 10c7ee4f6c8..ebdb86f98a8 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2020,7 +2020,7 @@ impl<T, A: Allocator> Vec<T, A> { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap_remove(&mut self, index: usize) -> T { #[cold] - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { @@ -2102,7 +2102,7 @@ impl<T, A: Allocator> Vec<T, A> { #[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"] pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T { #[cold] - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { @@ -2166,7 +2166,7 @@ impl<T, A: Allocator> Vec<T, A> { #[rustc_confusables("delete", "take")] pub fn remove(&mut self, index: usize) -> T { #[cold] - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[optimize(size)] fn assert_failed(index: usize, len: usize) -> ! { @@ -2955,7 +2955,7 @@ impl<T, A: Allocator> Vec<T, A> { A: Clone, { #[cold] - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] + #[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[optimize(size)] fn assert_failed(at: usize, len: usize) -> ! { diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index fb790e69615..b5ee6413d55 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -289,7 +289,7 @@ macro_rules! float_impl { cfg_if! { // fma is not yet available in `core` if #[cfg(intrinsics_enabled)] { - unsafe{ core::intrinsics::$fma_intrinsic(self, y, z) } + core::intrinsics::$fma_intrinsic(self, y, z) } else { super::super::$fma_fn(self, y, z) } diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3e34e03a61e..d094172b076 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -16,7 +16,7 @@ test = false bench = false [features] -# Make panics and failed asserts immediately abort without formatting any message +# Issue a compile error that says to use -Cpanic=immediate-abort panic_immediate_abort = [] # Choose algorithms that are optimized for binary size instead of runtime performance optimize_for_size = [] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 9b53b75ebee..7d4a66640b1 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -778,7 +778,7 @@ impl Display for BorrowMutError { } // This ensures the panicking code is outlined from `borrow_mut` for `RefCell`. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[cold] const fn panic_already_borrowed(err: BorrowMutError) -> ! { @@ -790,7 +790,7 @@ const fn panic_already_borrowed(err: BorrowMutError) -> ! { } // This ensures the panicking code is outlined from `borrow` for `RefCell`. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[cold] const fn panic_already_mutably_borrowed(err: BorrowError) -> ! { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index bffffbc29c1..eaf2738d8b7 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1022,28 +1022,28 @@ pub unsafe fn unaligned_volatile_store<T>(dst: *mut T, val: T); /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sqrtf16(x: f16) -> f16; +pub fn sqrtf16(x: f16) -> f16; /// Returns the square root of an `f32` /// /// The stabilized version of this intrinsic is /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sqrtf32(x: f32) -> f32; +pub fn sqrtf32(x: f32) -> f32; /// Returns the square root of an `f64` /// /// The stabilized version of this intrinsic is /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sqrtf64(x: f64) -> f64; +pub fn sqrtf64(x: f64) -> f64; /// Returns the square root of an `f128` /// /// The stabilized version of this intrinsic is /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sqrtf128(x: f128) -> f128; +pub fn sqrtf128(x: f128) -> f128; /// Raises an `f16` to an integer power. /// @@ -1051,28 +1051,28 @@ pub unsafe fn sqrtf128(x: f128) -> f128; /// [`f16::powi`](../../std/primitive.f16.html#method.powi) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powif16(a: f16, x: i32) -> f16; +pub fn powif16(a: f16, x: i32) -> f16; /// Raises an `f32` to an integer power. /// /// The stabilized version of this intrinsic is /// [`f32::powi`](../../std/primitive.f32.html#method.powi) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powif32(a: f32, x: i32) -> f32; +pub fn powif32(a: f32, x: i32) -> f32; /// Raises an `f64` to an integer power. /// /// The stabilized version of this intrinsic is /// [`f64::powi`](../../std/primitive.f64.html#method.powi) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powif64(a: f64, x: i32) -> f64; +pub fn powif64(a: f64, x: i32) -> f64; /// Raises an `f128` to an integer power. /// /// The stabilized version of this intrinsic is /// [`f128::powi`](../../std/primitive.f128.html#method.powi) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powif128(a: f128, x: i32) -> f128; +pub fn powif128(a: f128, x: i32) -> f128; /// Returns the sine of an `f16`. /// @@ -1080,28 +1080,28 @@ pub unsafe fn powif128(a: f128, x: i32) -> f128; /// [`f16::sin`](../../std/primitive.f16.html#method.sin) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sinf16(x: f16) -> f16; +pub fn sinf16(x: f16) -> f16; /// Returns the sine of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::sin`](../../std/primitive.f32.html#method.sin) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sinf32(x: f32) -> f32; +pub fn sinf32(x: f32) -> f32; /// Returns the sine of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::sin`](../../std/primitive.f64.html#method.sin) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sinf64(x: f64) -> f64; +pub fn sinf64(x: f64) -> f64; /// Returns the sine of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::sin`](../../std/primitive.f128.html#method.sin) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn sinf128(x: f128) -> f128; +pub fn sinf128(x: f128) -> f128; /// Returns the cosine of an `f16`. /// @@ -1109,28 +1109,28 @@ pub unsafe fn sinf128(x: f128) -> f128; /// [`f16::cos`](../../std/primitive.f16.html#method.cos) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn cosf16(x: f16) -> f16; +pub fn cosf16(x: f16) -> f16; /// Returns the cosine of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::cos`](../../std/primitive.f32.html#method.cos) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn cosf32(x: f32) -> f32; +pub fn cosf32(x: f32) -> f32; /// Returns the cosine of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::cos`](../../std/primitive.f64.html#method.cos) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn cosf64(x: f64) -> f64; +pub fn cosf64(x: f64) -> f64; /// Returns the cosine of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::cos`](../../std/primitive.f128.html#method.cos) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn cosf128(x: f128) -> f128; +pub fn cosf128(x: f128) -> f128; /// Raises an `f16` to an `f16` power. /// @@ -1138,28 +1138,28 @@ pub unsafe fn cosf128(x: f128) -> f128; /// [`f16::powf`](../../std/primitive.f16.html#method.powf) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powf16(a: f16, x: f16) -> f16; +pub fn powf16(a: f16, x: f16) -> f16; /// Raises an `f32` to an `f32` power. /// /// The stabilized version of this intrinsic is /// [`f32::powf`](../../std/primitive.f32.html#method.powf) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powf32(a: f32, x: f32) -> f32; +pub fn powf32(a: f32, x: f32) -> f32; /// Raises an `f64` to an `f64` power. /// /// The stabilized version of this intrinsic is /// [`f64::powf`](../../std/primitive.f64.html#method.powf) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powf64(a: f64, x: f64) -> f64; +pub fn powf64(a: f64, x: f64) -> f64; /// Raises an `f128` to an `f128` power. /// /// The stabilized version of this intrinsic is /// [`f128::powf`](../../std/primitive.f128.html#method.powf) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn powf128(a: f128, x: f128) -> f128; +pub fn powf128(a: f128, x: f128) -> f128; /// Returns the exponential of an `f16`. /// @@ -1167,28 +1167,28 @@ pub unsafe fn powf128(a: f128, x: f128) -> f128; /// [`f16::exp`](../../std/primitive.f16.html#method.exp) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn expf16(x: f16) -> f16; +pub fn expf16(x: f16) -> f16; /// Returns the exponential of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::exp`](../../std/primitive.f32.html#method.exp) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn expf32(x: f32) -> f32; +pub fn expf32(x: f32) -> f32; /// Returns the exponential of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::exp`](../../std/primitive.f64.html#method.exp) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn expf64(x: f64) -> f64; +pub fn expf64(x: f64) -> f64; /// Returns the exponential of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::exp`](../../std/primitive.f128.html#method.exp) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn expf128(x: f128) -> f128; +pub fn expf128(x: f128) -> f128; /// Returns 2 raised to the power of an `f16`. /// @@ -1196,28 +1196,28 @@ pub unsafe fn expf128(x: f128) -> f128; /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn exp2f16(x: f16) -> f16; +pub fn exp2f16(x: f16) -> f16; /// Returns 2 raised to the power of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn exp2f32(x: f32) -> f32; +pub fn exp2f32(x: f32) -> f32; /// Returns 2 raised to the power of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn exp2f64(x: f64) -> f64; +pub fn exp2f64(x: f64) -> f64; /// Returns 2 raised to the power of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn exp2f128(x: f128) -> f128; +pub fn exp2f128(x: f128) -> f128; /// Returns the natural logarithm of an `f16`. /// @@ -1225,28 +1225,28 @@ pub unsafe fn exp2f128(x: f128) -> f128; /// [`f16::ln`](../../std/primitive.f16.html#method.ln) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn logf16(x: f16) -> f16; +pub fn logf16(x: f16) -> f16; /// Returns the natural logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::ln`](../../std/primitive.f32.html#method.ln) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn logf32(x: f32) -> f32; +pub fn logf32(x: f32) -> f32; /// Returns the natural logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::ln`](../../std/primitive.f64.html#method.ln) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn logf64(x: f64) -> f64; +pub fn logf64(x: f64) -> f64; /// Returns the natural logarithm of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::ln`](../../std/primitive.f128.html#method.ln) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn logf128(x: f128) -> f128; +pub fn logf128(x: f128) -> f128; /// Returns the base 10 logarithm of an `f16`. /// @@ -1254,28 +1254,28 @@ pub unsafe fn logf128(x: f128) -> f128; /// [`f16::log10`](../../std/primitive.f16.html#method.log10) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log10f16(x: f16) -> f16; +pub fn log10f16(x: f16) -> f16; /// Returns the base 10 logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::log10`](../../std/primitive.f32.html#method.log10) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log10f32(x: f32) -> f32; +pub fn log10f32(x: f32) -> f32; /// Returns the base 10 logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::log10`](../../std/primitive.f64.html#method.log10) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log10f64(x: f64) -> f64; +pub fn log10f64(x: f64) -> f64; /// Returns the base 10 logarithm of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::log10`](../../std/primitive.f128.html#method.log10) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log10f128(x: f128) -> f128; +pub fn log10f128(x: f128) -> f128; /// Returns the base 2 logarithm of an `f16`. /// @@ -1283,28 +1283,28 @@ pub unsafe fn log10f128(x: f128) -> f128; /// [`f16::log2`](../../std/primitive.f16.html#method.log2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log2f16(x: f16) -> f16; +pub fn log2f16(x: f16) -> f16; /// Returns the base 2 logarithm of an `f32`. /// /// The stabilized version of this intrinsic is /// [`f32::log2`](../../std/primitive.f32.html#method.log2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log2f32(x: f32) -> f32; +pub fn log2f32(x: f32) -> f32; /// Returns the base 2 logarithm of an `f64`. /// /// The stabilized version of this intrinsic is /// [`f64::log2`](../../std/primitive.f64.html#method.log2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log2f64(x: f64) -> f64; +pub fn log2f64(x: f64) -> f64; /// Returns the base 2 logarithm of an `f128`. /// /// The stabilized version of this intrinsic is /// [`f128::log2`](../../std/primitive.f128.html#method.log2) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn log2f128(x: f128) -> f128; +pub fn log2f128(x: f128) -> f128; /// Returns `a * b + c` for `f16` values. /// @@ -1312,28 +1312,28 @@ pub unsafe fn log2f128(x: f128) -> f128; /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmaf16(a: f16, b: f16, c: f16) -> f16; +pub fn fmaf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values. /// /// The stabilized version of this intrinsic is /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmaf32(a: f32, b: f32, c: f32) -> f32; +pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values. /// /// The stabilized version of this intrinsic is /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmaf64(a: f64, b: f64, c: f64) -> f64; +pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values. /// /// The stabilized version of this intrinsic is /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmaf128(a: f128, b: f128, c: f128) -> f128; +pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// Returns `a * b + c` for `f16` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1347,7 +1347,7 @@ pub unsafe fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; +pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1360,7 +1360,7 @@ pub unsafe fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; +pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1373,7 +1373,7 @@ pub unsafe fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; +pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1386,7 +1386,7 @@ pub unsafe fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; +pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; /// Returns the largest integer less than or equal to an `f16`. /// @@ -1395,7 +1395,7 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn floorf16(x: f16) -> f16; +pub const fn floorf16(x: f16) -> f16; /// Returns the largest integer less than or equal to an `f32`. /// /// The stabilized version of this intrinsic is @@ -1403,7 +1403,7 @@ pub const unsafe fn floorf16(x: f16) -> f16; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn floorf32(x: f32) -> f32; +pub const fn floorf32(x: f32) -> f32; /// Returns the largest integer less than or equal to an `f64`. /// /// The stabilized version of this intrinsic is @@ -1411,7 +1411,7 @@ pub const unsafe fn floorf32(x: f32) -> f32; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn floorf64(x: f64) -> f64; +pub const fn floorf64(x: f64) -> f64; /// Returns the largest integer less than or equal to an `f128`. /// /// The stabilized version of this intrinsic is @@ -1419,7 +1419,7 @@ pub const unsafe fn floorf64(x: f64) -> f64; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn floorf128(x: f128) -> f128; +pub const fn floorf128(x: f128) -> f128; /// Returns the smallest integer greater than or equal to an `f16`. /// @@ -1428,7 +1428,7 @@ pub const unsafe fn floorf128(x: f128) -> f128; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn ceilf16(x: f16) -> f16; +pub const fn ceilf16(x: f16) -> f16; /// Returns the smallest integer greater than or equal to an `f32`. /// /// The stabilized version of this intrinsic is @@ -1436,7 +1436,7 @@ pub const unsafe fn ceilf16(x: f16) -> f16; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn ceilf32(x: f32) -> f32; +pub const fn ceilf32(x: f32) -> f32; /// Returns the smallest integer greater than or equal to an `f64`. /// /// The stabilized version of this intrinsic is @@ -1444,7 +1444,7 @@ pub const unsafe fn ceilf32(x: f32) -> f32; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn ceilf64(x: f64) -> f64; +pub const fn ceilf64(x: f64) -> f64; /// Returns the smallest integer greater than or equal to an `f128`. /// /// The stabilized version of this intrinsic is @@ -1452,7 +1452,7 @@ pub const unsafe fn ceilf64(x: f64) -> f64; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn ceilf128(x: f128) -> f128; +pub const fn ceilf128(x: f128) -> f128; /// Returns the integer part of an `f16`. /// @@ -1461,7 +1461,7 @@ pub const unsafe fn ceilf128(x: f128) -> f128; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn truncf16(x: f16) -> f16; +pub const fn truncf16(x: f16) -> f16; /// Returns the integer part of an `f32`. /// /// The stabilized version of this intrinsic is @@ -1469,7 +1469,7 @@ pub const unsafe fn truncf16(x: f16) -> f16; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn truncf32(x: f32) -> f32; +pub const fn truncf32(x: f32) -> f32; /// Returns the integer part of an `f64`. /// /// The stabilized version of this intrinsic is @@ -1477,7 +1477,7 @@ pub const unsafe fn truncf32(x: f32) -> f32; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn truncf64(x: f64) -> f64; +pub const fn truncf64(x: f64) -> f64; /// Returns the integer part of an `f128`. /// /// The stabilized version of this intrinsic is @@ -1485,7 +1485,7 @@ pub const unsafe fn truncf64(x: f64) -> f64; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn truncf128(x: f128) -> f128; +pub const fn truncf128(x: f128) -> f128; /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even /// least significant digit. @@ -1534,7 +1534,7 @@ pub const fn round_ties_even_f128(x: f128) -> f128; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn roundf16(x: f16) -> f16; +pub const fn roundf16(x: f16) -> f16; /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is @@ -1542,7 +1542,7 @@ pub const unsafe fn roundf16(x: f16) -> f16; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn roundf32(x: f32) -> f32; +pub const fn roundf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is @@ -1550,7 +1550,7 @@ pub const unsafe fn roundf32(x: f32) -> f32; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn roundf64(x: f64) -> f64; +pub const fn roundf64(x: f64) -> f64; /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is @@ -1558,10 +1558,10 @@ pub const unsafe fn roundf64(x: f64) -> f64; #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn roundf128(x: f128) -> f128; +pub const fn roundf128(x: f128) -> f128; /// Float addition that allows optimizations based on algebraic rules. -/// May assume inputs are finite. +/// Requires that inputs and output of the operation are finite, causing UB otherwise. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] @@ -1569,7 +1569,7 @@ pub const unsafe fn roundf128(x: f128) -> f128; pub unsafe fn fadd_fast<T: Copy>(a: T, b: T) -> T; /// Float subtraction that allows optimizations based on algebraic rules. -/// May assume inputs are finite. +/// Requires that inputs and output of the operation are finite, causing UB otherwise. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] @@ -1577,7 +1577,7 @@ pub unsafe fn fadd_fast<T: Copy>(a: T, b: T) -> T; pub unsafe fn fsub_fast<T: Copy>(a: T, b: T) -> T; /// Float multiplication that allows optimizations based on algebraic rules. -/// May assume inputs are finite. +/// Requires that inputs and output of the operation are finite, causing UB otherwise. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] @@ -1585,7 +1585,7 @@ pub unsafe fn fsub_fast<T: Copy>(a: T, b: T) -> T; pub unsafe fn fmul_fast<T: Copy>(a: T, b: T) -> T; /// Float division that allows optimizations based on algebraic rules. -/// May assume inputs are finite. +/// Requires that inputs and output of the operation are finite, causing UB otherwise. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] @@ -1593,7 +1593,7 @@ pub unsafe fn fmul_fast<T: Copy>(a: T, b: T) -> T; pub unsafe fn fdiv_fast<T: Copy>(a: T, b: T) -> T; /// Float remainder that allows optimizations based on algebraic rules. -/// May assume inputs are finite. +/// Requires that inputs and output of the operation are finite, causing UB otherwise. /// /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] @@ -3170,7 +3170,7 @@ pub const fn maximumf128(x: f128, y: f128) -> f128 { /// [`f16::abs`](../../std/primitive.f16.html#method.abs) #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn fabsf16(x: f16) -> f16; +pub const fn fabsf16(x: f16) -> f16; /// Returns the absolute value of an `f32`. /// @@ -3179,7 +3179,7 @@ pub const unsafe fn fabsf16(x: f16) -> f16; #[rustc_nounwind] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const unsafe fn fabsf32(x: f32) -> f32; +pub const fn fabsf32(x: f32) -> f32; /// Returns the absolute value of an `f64`. /// @@ -3188,7 +3188,7 @@ pub const unsafe fn fabsf32(x: f32) -> f32; #[rustc_nounwind] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const unsafe fn fabsf64(x: f64) -> f64; +pub const fn fabsf64(x: f64) -> f64; /// Returns the absolute value of an `f128`. /// @@ -3196,7 +3196,7 @@ pub const unsafe fn fabsf64(x: f64) -> f64; /// [`f128::abs`](../../std/primitive.f128.html#method.abs) #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn fabsf128(x: f128) -> f128; +pub const fn fabsf128(x: f128) -> f128; /// Copies the sign from `y` to `x` for `f16` values. /// @@ -3204,7 +3204,7 @@ pub const unsafe fn fabsf128(x: f128) -> f128; /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn copysignf16(x: f16, y: f16) -> f16; +pub const fn copysignf16(x: f16, y: f16) -> f16; /// Copies the sign from `y` to `x` for `f32` values. /// @@ -3213,7 +3213,7 @@ pub const unsafe fn copysignf16(x: f16, y: f16) -> f16; #[rustc_nounwind] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const unsafe fn copysignf32(x: f32, y: f32) -> f32; +pub const fn copysignf32(x: f32, y: f32) -> f32; /// Copies the sign from `y` to `x` for `f64` values. /// /// The stabilized version of this intrinsic is @@ -3221,7 +3221,7 @@ pub const unsafe fn copysignf32(x: f32, y: f32) -> f32; #[rustc_nounwind] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const unsafe fn copysignf64(x: f64, y: f64) -> f64; +pub const fn copysignf64(x: f64, y: f64) -> f64; /// Copies the sign from `y` to `x` for `f128` values. /// @@ -3229,7 +3229,7 @@ pub const unsafe fn copysignf64(x: f64, y: f64) -> f64; /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) #[rustc_nounwind] #[rustc_intrinsic] -pub const unsafe fn copysignf128(x: f128, y: f128) -> f128; +pub const fn copysignf128(x: f128, y: f128) -> f128; /// Generates the LLVM body for the automatic differentiation of `f` using Enzyme, /// with `df` as the derivative function and `args` as its arguments. diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index a820045521b..c50f07ff6bb 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -779,7 +779,7 @@ impl<T> OneShot for result::IterMut<'_, T> {} impl<T> OneShot for Empty<T> {} impl<T> OneShot for array::IntoIter<T, 0> {} -// These adaptors never increase the number of items. +// These adapters never increase the number of items. // (There are more possible, but for now this matches BoundedSize above.) impl<I: OneShot> OneShot for Cloned<I> {} impl<I: OneShot> OneShot for Copied<I> {} diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 66c892aadd0..3b03cde0372 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1196,7 +1196,8 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i128; let mut right = other.to_bits() as i128; @@ -1366,8 +1367,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn copysign(self, sign: f128) -> f128 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::copysignf128(self, sign) } + intrinsics::copysignf128(self, sign) } /// Float addition that allows optimizations based on algebraic rules. @@ -1459,8 +1459,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn floor(self) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::floorf128(self) } + intrinsics::floorf128(self) } /// Returns the smallest integer greater than or equal to `self`. @@ -1488,8 +1487,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn ceil(self) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::ceilf128(self) } + intrinsics::ceilf128(self) } /// Returns the nearest integer to `self`. If a value is half-way between two @@ -1523,8 +1521,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn round(self) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::roundf128(self) } + intrinsics::roundf128(self) } /// Returns the nearest integer to a number. Rounds half-way cases to the number @@ -1587,8 +1584,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn trunc(self) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::truncf128(self) } + intrinsics::truncf128(self) } /// Returns the fractional part of `self`. @@ -1664,8 +1660,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn mul_add(self, a: f128, b: f128) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::fmaf128(self, a, b) } + intrinsics::fmaf128(self, a, b) } /// Calculates Euclidean division, the matching method for `rem_euclid`. @@ -1780,8 +1775,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn powi(self, n: i32) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::powif128(self, n) } + intrinsics::powif128(self, n) } /// Returns the square root of a number. @@ -1816,7 +1810,6 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sqrt(self) -> f128 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::sqrtf128(self) } + intrinsics::sqrtf128(self) } } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 81220065e72..a027d63005b 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1175,7 +1175,8 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i16; let mut right = other.to_bits() as i16; @@ -1343,8 +1344,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn copysign(self, sign: f16) -> f16 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::copysignf16(self, sign) } + intrinsics::copysignf16(self, sign) } /// Float addition that allows optimizations based on algebraic rules. @@ -1434,8 +1434,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn floor(self) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::floorf16(self) } + intrinsics::floorf16(self) } /// Returns the smallest integer greater than or equal to `self`. @@ -1463,8 +1462,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn ceil(self) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::ceilf16(self) } + intrinsics::ceilf16(self) } /// Returns the nearest integer to `self`. If a value is half-way between two @@ -1498,8 +1496,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn round(self) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::roundf16(self) } + intrinsics::roundf16(self) } /// Returns the nearest integer to a number. Rounds half-way cases to the number @@ -1562,8 +1559,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn trunc(self) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::truncf16(self) } + intrinsics::truncf16(self) } /// Returns the fractional part of `self`. @@ -1639,8 +1635,7 @@ impl f16 { #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn mul_add(self, a: f16, b: f16) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::fmaf16(self, a, b) } + intrinsics::fmaf16(self, a, b) } /// Calculates Euclidean division, the matching method for `rem_euclid`. @@ -1755,8 +1750,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn powi(self, n: i32) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::powif16(self, n) } + intrinsics::powif16(self, n) } /// Returns the square root of a number. @@ -1791,8 +1785,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sqrt(self) -> f16 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::sqrtf16(self) } + intrinsics::sqrtf16(self) } /// Returns the cube root of a number. diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index cefcf1d1fe2..bfc091c54b2 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1353,9 +1353,10 @@ impl f32 { /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[must_use] #[inline] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i32; let mut right = other.to_bits() as i32; @@ -1449,8 +1450,7 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f32 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::fabsf32(self) } + intrinsics::fabsf32(self) } /// Returns a number that represents the sign of `self`. @@ -1508,8 +1508,7 @@ impl f32 { #[stable(feature = "copysign", since = "1.35.0")] #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] pub const fn copysign(self, sign: f32) -> f32 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::copysignf32(self, sign) } + intrinsics::copysignf32(self, sign) } /// Float addition that allows optimizations based on algebraic rules. @@ -1603,8 +1602,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn floor(x: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::floorf32(x) } + intrinsics::floorf32(x) } /// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details. @@ -1632,8 +1630,7 @@ pub mod math { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "core_float_math", issue = "137578")] pub const fn ceil(x: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::ceilf32(x) } + intrinsics::ceilf32(x) } /// Experimental version of `round` in `core`. See [`f32::round`] for details. @@ -1666,8 +1663,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn round(x: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::roundf32(x) } + intrinsics::roundf32(x) } /// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for @@ -1729,8 +1725,7 @@ pub mod math { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "core_float_math", issue = "137578")] pub const fn trunc(x: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::truncf32(x) } + intrinsics::truncf32(x) } /// Experimental version of `fract` in `core`. See [`f32::fract`] for details. @@ -1804,8 +1799,7 @@ pub mod math { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "core_float_math", issue = "137578")] pub fn mul_add(x: f32, y: f32, z: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::fmaf32(x, y, z) } + intrinsics::fmaf32(x, y, z) } /// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details. @@ -1896,8 +1890,7 @@ pub mod math { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "core_float_math", issue = "137578")] pub fn powi(x: f32, n: i32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::powif32(x, n) } + intrinsics::powif32(x, n) } /// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details. @@ -1927,8 +1920,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sqrt(x: f32) -> f32 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::sqrtf32(x) } + intrinsics::sqrtf32(x) } /// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 9dd1141e703..21cd77d8014 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1351,9 +1351,10 @@ impl f64 { /// } /// ``` #[stable(feature = "total_cmp", since = "1.62.0")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[must_use] #[inline] - pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { let mut left = self.to_bits() as i64; let mut right = other.to_bits() as i64; @@ -1447,8 +1448,7 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f64 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::fabsf64(self) } + intrinsics::fabsf64(self) } /// Returns a number that represents the sign of `self`. @@ -1506,8 +1506,7 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn copysign(self, sign: f64) -> f64 { - // SAFETY: this is actually a safe intrinsic - unsafe { intrinsics::copysignf64(self, sign) } + intrinsics::copysignf64(self, sign) } /// Float addition that allows optimizations based on algebraic rules. @@ -1601,8 +1600,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn floor(x: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::floorf64(x) } + intrinsics::floorf64(x) } /// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details. @@ -1630,8 +1628,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn ceil(x: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::ceilf64(x) } + intrinsics::ceilf64(x) } /// Experimental version of `round` in `core`. See [`f64::round`] for details. @@ -1664,8 +1661,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn round(x: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::roundf64(x) } + intrinsics::roundf64(x) } /// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for @@ -1727,8 +1723,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn trunc(x: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::truncf64(x) } + intrinsics::truncf64(x) } /// Experimental version of `fract` in `core`. See [`f64::fract`] for details. @@ -1802,8 +1797,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn mul_add(x: f64, a: f64, b: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::fmaf64(x, a, b) } + intrinsics::fmaf64(x, a, b) } /// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details. @@ -1894,8 +1888,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn powi(x: f64, n: i32) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::powif64(x, n) } + intrinsics::powif64(x, n) } /// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details. @@ -1925,8 +1918,7 @@ pub mod math { #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sqrt(x: f64) -> f64 { - // SAFETY: intrinsic with no preconditions - unsafe { intrinsics::sqrtf64(x) } + intrinsics::sqrtf64(x) } /// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 54d5a63633c..c75ee11d15e 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1387,8 +1387,8 @@ pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) radix <= 16 && digits.len() <= size_of::<T>() * 2 - is_signed_ty as usize } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] +#[cfg_attr(panic = "immediate-abort", inline)] #[cold] #[track_caller] const fn from_ascii_radix_panic(radix: u32) -> ! { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 886d581b0a6..430ee3470ac 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2161,8 +2161,8 @@ impl<T, E> Option<Result<T, E>> { } } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] +#[cfg_attr(panic = "immediate-abort", inline)] #[cold] #[track_caller] const fn unwrap_failed() -> ! { @@ -2170,8 +2170,8 @@ const fn unwrap_failed() -> ! { } // This is a separate function to reduce the code size of .expect() itself. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] +#[cfg_attr(panic = "immediate-abort", inline)] #[cold] #[track_caller] const fn expect_failed(msg: &str) -> ! { diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 804a12ee477..3f30038dbc0 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -33,7 +33,10 @@ use crate::intrinsics::const_eval_select; use crate::panic::{Location, PanicInfo}; #[cfg(feature = "panic_immediate_abort")] -const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C panic=abort"); +compile_error!( + "panic_immediate_abort is now a real panic strategy! \ + Enable it with the compiler flags `-Zunstable-options -Cpanic=immediate-abort`" +); // First we define the two main entry points that all panics go through. // In the end both are just convenience wrappers around `panic_impl`. @@ -44,16 +47,16 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C /// site as much as possible (so that `panic!()` has as low an impact /// on (e.g.) the inlining of other functions as possible), by moving /// the actual formatting into this shared place. -// If panic_immediate_abort, inline the abort call, +// If panic=immediate-abort, inline the abort call, // otherwise avoid inlining because of it is cold path. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics #[rustc_do_not_const_check] // hooked by const-eval #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } @@ -78,8 +81,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { /// Like `panic_fmt`, but for non-unwinding panics. /// /// Has to be a separate function so that it can carry the `rustc_nounwind` attribute. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] // This attribute has the key side-effect that if the panic handler ignores `can_unwind` // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, @@ -94,7 +97,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`. panic_fmt(fmt) } else #[track_caller] { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } @@ -123,10 +126,10 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo // above. /// The underlying implementation of core's `panic!` macro when no formatting is used. -// Never inline unless panic_immediate_abort to avoid code +// Never inline unless panic=immediate-abort to avoid code // bloat at the call sites as much as possible. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = "panic"] // used by lints and miri for panics @@ -158,10 +161,10 @@ macro_rules! panic_const { $( /// This is a panic called with a message that's a result of a MIR-produced Assert. // - // never inline unless panic_immediate_abort to avoid code + // never inline unless panic=immediate-abort to avoid code // bloat at the call sites as much as possible - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] - #[cfg_attr(feature = "panic_immediate_abort", inline)] + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = stringify!($lang)] @@ -216,8 +219,8 @@ pub mod panic_const { /// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller. /// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable @@ -226,8 +229,8 @@ pub const fn panic_nounwind(expr: &'static str) -> ! { } /// Like `panic_nounwind`, but also inhibits showing a backtrace. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[rustc_nounwind] pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true); @@ -259,25 +262,25 @@ pub const fn panic_display<T: fmt::Display>(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access fn panic_bounds_check(index: usize, len: usize) -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } panic!("index out of bounds: the len is {len} but the index is {index}") } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref #[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } @@ -289,13 +292,13 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { ) } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[lang = "panic_null_pointer_dereference"] // needed by codegen for panic on null pointer deref #[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind fn panic_null_pointer_dereference() -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } @@ -305,13 +308,13 @@ fn panic_null_pointer_dereference() -> ! { ) } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[lang = "panic_invalid_enum_construction"] // needed by codegen for panic on invalid enum construction. #[rustc_nounwind] // `CheckEnums` MIR pass requires this function to never unwind fn panic_invalid_enum_construction(source: u128) -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { super::intrinsics::abort() } @@ -328,8 +331,8 @@ fn panic_invalid_enum_construction(source: u128) -> ! { /// /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function #[rustc_nounwind] fn panic_cannot_unwind() -> ! { @@ -344,8 +347,8 @@ fn panic_cannot_unwind() -> ! { /// /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function #[rustc_nounwind] fn panic_in_cleanup() -> ! { @@ -377,8 +380,8 @@ pub enum AssertKind { } /// Internal function for `assert_eq!` and `assert_ne!` macros -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[doc(hidden)] pub fn assert_failed<T, U>( @@ -395,8 +398,8 @@ where } /// Internal function for `assert_match!` -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[doc(hidden)] pub fn assert_matches_failed<T: fmt::Debug + ?Sized>( @@ -415,8 +418,8 @@ pub fn assert_matches_failed<T: fmt::Debug + ?Sized>( } /// Non-generic version of the above functions, to avoid code bloat. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] fn assert_failed_inner( kind: AssertKind, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 5c1f64bfe14..c69762a7285 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1847,7 +1847,7 @@ impl<T, E> Result<Result<T, E>, E> { } // This is a separate function to reduce the code size of the methods -#[cfg(not(feature = "panic_immediate_abort"))] +#[cfg(not(panic = "immediate-abort"))] #[inline(never)] #[cold] #[track_caller] @@ -1859,7 +1859,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { // that gets immediately thrown away, since vtables don't get cleaned up // by dead code elimination if a trait object is constructed even if it goes // unused -#[cfg(feature = "panic_immediate_abort")] +#[cfg(panic = "immediate-abort")] #[inline] #[cold] #[track_caller] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index d4c466201ed..de220e7e38a 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -31,8 +31,8 @@ where } } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] const fn slice_index_fail(start: usize, end: usize, len: usize) -> ! { if start > len { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index dfbb3628350..f7f5ee819b2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3858,8 +3858,8 @@ impl<T> [T] { { // The panic code path was put into a cold function to not bloat the // call site. - #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] - #[cfg_attr(feature = "panic_immediate_abort", inline)] + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { const_panic!( diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index 400daba16c1..e555fce4408 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -840,8 +840,8 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>( } } -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] +#[cfg_attr(panic = "immediate-abort", inline)] fn panic_on_ord_violation() -> ! { // This is indicative of a logic bug in the user-provided comparison function or Ord // implementation. They are expected to implement a total order as explained in the Ord diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 04fdaa8143e..2e473d348b0 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -64,12 +64,12 @@ pub use validations::{next_code_point, utf8_char_width}; #[cold] #[track_caller] #[rustc_allow_const_fn_unstable(const_eval_select)] -#[cfg(not(feature = "panic_immediate_abort"))] +#[cfg(not(panic = "immediate-abort"))] const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { crate::intrinsics::const_eval_select((s, begin, end), slice_error_fail_ct, slice_error_fail_rt) } -#[cfg(feature = "panic_immediate_abort")] +#[cfg(panic = "immediate-abort")] const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { slice_error_fail_ct(s, begin, end) } diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 31515561c63..d2b57223094 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -1246,104 +1246,103 @@ float_test! { float_test! { name: total_cmp, attrs: { - const: #[cfg(false)], f16: #[cfg(all(not(miri), target_has_reliable_f16_math))], f128: #[cfg(all(not(miri), target_has_reliable_f128_math))], }, test<Float> { use core::cmp::Ordering; - fn quiet_bit_mask() -> <Float as TestableFloat>::Int { + const fn quiet_bit_mask() -> <Float as TestableFloat>::Int { 1 << (Float::MANTISSA_DIGITS - 2) } - fn q_nan() -> Float { + const fn q_nan() -> Float { Float::from_bits(Float::NAN.to_bits() | quiet_bit_mask()) } - assert_eq!(Ordering::Equal, Float::total_cmp(&-q_nan(), &-q_nan())); - assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::INFINITY, &-Float::INFINITY)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MAX, &-Float::MAX)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-2.5, &-2.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-1.0, &-1.0)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-1.5, &-1.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-0.5, &-0.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MIN_POSITIVE)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::TINY, &-Float::TINY)); - assert_eq!(Ordering::Equal, Float::total_cmp(&-0.0, &-0.0)); - assert_eq!(Ordering::Equal, Float::total_cmp(&0.0, &0.0)); - assert_eq!(Ordering::Equal, Float::total_cmp(&Float::TINY, &Float::TINY)); - assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MIN_POSITIVE, &Float::MIN_POSITIVE)); - assert_eq!(Ordering::Equal, Float::total_cmp(&0.5, &0.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&1.0, &1.0)); - assert_eq!(Ordering::Equal, Float::total_cmp(&1.5, &1.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&2.5, &2.5)); - assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MAX, &Float::MAX)); - assert_eq!(Ordering::Equal, Float::total_cmp(&Float::INFINITY, &Float::INFINITY)); - assert_eq!(Ordering::Equal, Float::total_cmp(&q_nan(), &q_nan())); - - assert_eq!(Ordering::Less, Float::total_cmp(&-Float::INFINITY, &-Float::MAX)); - assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MAX, &-2.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-2.5, &-1.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-1.5, &-1.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-1.0, &-0.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-0.5, &-Float::MIN_POSITIVE)); - assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::TINY)); - assert_eq!(Ordering::Less, Float::total_cmp(&-Float::TINY, &-0.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-0.0, &0.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&0.0, &Float::TINY)); - assert_eq!(Ordering::Less, Float::total_cmp(&Float::TINY, &Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Less, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MIN_POSITIVE)); - assert_eq!(Ordering::Less, Float::total_cmp(&Float::MIN_POSITIVE, &0.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&0.5, &1.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&1.0, &1.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&1.5, &2.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&2.5, &Float::MAX)); - assert_eq!(Ordering::Less, Float::total_cmp(&Float::MAX, &Float::INFINITY)); - - assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MAX, &-Float::INFINITY)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-2.5, &-Float::MAX)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-1.5, &-2.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-1.0, &-1.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-0.5, &-1.0)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MIN_POSITIVE, &-0.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MIN_POSITIVE)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::TINY, &-Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Greater, Float::total_cmp(&-0.0, &-Float::TINY)); - assert_eq!(Ordering::Greater, Float::total_cmp(&0.0, &-0.0)); - assert_eq!(Ordering::Greater, Float::total_cmp(&Float::TINY, &0.0)); - assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::TINY)); - assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MIN_POSITIVE, &Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Greater, Float::total_cmp(&0.5, &Float::MIN_POSITIVE)); - assert_eq!(Ordering::Greater, Float::total_cmp(&1.0, &0.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&1.5, &1.0)); - assert_eq!(Ordering::Greater, Float::total_cmp(&2.5, &1.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MAX, &2.5)); - assert_eq!(Ordering::Greater, Float::total_cmp(&Float::INFINITY, &Float::MAX)); - - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::INFINITY)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MAX)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-2.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-1.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-1.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-0.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MIN_POSITIVE)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::TINY)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-0.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &0.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::TINY)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MAX_SUBNORMAL)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MIN_POSITIVE)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &0.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &1.0)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &1.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &2.5)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MAX)); - assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::INFINITY)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-q_nan()), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-Float::INFINITY, &-Float::INFINITY), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-Float::MAX, &-Float::MAX), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-2.5, &-2.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-1.0, &-1.0), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-1.5, &-1.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-0.5, &-0.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MIN_POSITIVE), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MAX_SUBNORMAL), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-Float::TINY, &-Float::TINY), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&-0.0, &-0.0), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&0.0, &0.0), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&Float::TINY, &Float::TINY), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MAX_SUBNORMAL), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&Float::MIN_POSITIVE, &Float::MIN_POSITIVE), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&0.5, &0.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&1.0, &1.0), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&1.5, &1.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&2.5, &2.5), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&Float::MAX, &Float::MAX), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&Float::INFINITY, &Float::INFINITY), Ordering::Equal)); + assert!(matches!(Float::total_cmp(&q_nan(), &q_nan()), Ordering::Equal)); + + assert!(matches!(Float::total_cmp(&-Float::INFINITY, &-Float::MAX), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-Float::MAX, &-2.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-2.5, &-1.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-1.5, &-1.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-1.0, &-0.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-0.5, &-Float::MIN_POSITIVE), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MAX_SUBNORMAL), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::TINY), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-Float::TINY, &-0.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-0.0, &0.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&0.0, &Float::TINY), Ordering::Less)); + assert!(matches!(Float::total_cmp(&Float::TINY, &Float::MAX_SUBNORMAL), Ordering::Less)); + assert!(matches!(Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MIN_POSITIVE), Ordering::Less)); + assert!(matches!(Float::total_cmp(&Float::MIN_POSITIVE, &0.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&0.5, &1.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&1.0, &1.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&1.5, &2.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&2.5, &Float::MAX), Ordering::Less)); + assert!(matches!(Float::total_cmp(&Float::MAX, &Float::INFINITY), Ordering::Less)); + + assert!(matches!(Float::total_cmp(&-Float::MAX, &-Float::INFINITY), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-2.5, &-Float::MAX), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-1.5, &-2.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-1.0, &-1.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-0.5, &-1.0), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-Float::MIN_POSITIVE, &-0.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MIN_POSITIVE), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-Float::TINY, &-Float::MAX_SUBNORMAL), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&-0.0, &-Float::TINY), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&0.0, &-0.0), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&Float::TINY, &0.0), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::TINY), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&Float::MIN_POSITIVE, &Float::MAX_SUBNORMAL), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&0.5, &Float::MIN_POSITIVE), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&1.0, &0.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&1.5, &1.0), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&2.5, &1.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&Float::MAX, &2.5), Ordering::Greater)); + assert!(matches!(Float::total_cmp(&Float::INFINITY, &Float::MAX), Ordering::Greater)); + + assert!(matches!(Float::total_cmp(&-q_nan(), &-Float::INFINITY), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-Float::MAX), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-2.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-1.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-1.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-0.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-Float::MIN_POSITIVE), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-Float::MAX_SUBNORMAL), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-Float::TINY), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &-0.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &0.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &Float::TINY), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &Float::MAX_SUBNORMAL), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &Float::MIN_POSITIVE), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &0.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &1.0), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &1.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &2.5), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &Float::MAX), Ordering::Less)); + assert!(matches!(Float::total_cmp(&-q_nan(), &Float::INFINITY), Ordering::Less)); } } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index d28a7f0b460..958cafb8f3d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -106,11 +106,6 @@ compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"] llvm-libunwind = ["unwind/llvm-libunwind"] system-llvm-libunwind = ["unwind/system-llvm-libunwind"] -# Make panics and failed asserts immediately abort without formatting any message -panic_immediate_abort = [ - "core/panic_immediate_abort", - "alloc/panic_immediate_abort", -] # Choose algorithms that are optimized for binary size instead of runtime performance optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"] diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ff0e29e04c2..a45edd08e8c 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1081,7 +1081,7 @@ pub trait Read { default_read_buf_exact(self, cursor) } - /// Creates a "by reference" adaptor for this instance of `Read`. + /// Creates a "by reference" adapter for this instance of `Read`. /// /// The returned adapter also implements `Read` and will simply borrow this /// current reader. diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs index b83692390b6..5d206c4b7da 100644 --- a/library/std/src/num/f128.rs +++ b/library/std/src/num/f128.rs @@ -44,7 +44,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn powf(self, n: f128) -> f128 { - unsafe { intrinsics::powf128(self, n) } + intrinsics::powf128(self, n) } /// Returns `e^(self)`, (the exponential function). @@ -76,7 +76,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp(self) -> f128 { - unsafe { intrinsics::expf128(self) } + intrinsics::expf128(self) } /// Returns `2^(self)`. @@ -106,7 +106,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp2(self) -> f128 { - unsafe { intrinsics::exp2f128(self) } + intrinsics::exp2f128(self) } /// Returns the natural logarithm of the number. @@ -151,7 +151,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln(self) -> f128 { - unsafe { intrinsics::logf128(self) } + intrinsics::logf128(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -241,7 +241,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log2(self) -> f128 { - unsafe { intrinsics::log2f128(self) } + intrinsics::log2f128(self) } /// Returns the base 10 logarithm of the number. @@ -284,7 +284,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log10(self) -> f128 { - unsafe { intrinsics::log10f128(self) } + intrinsics::log10f128(self) } /// Returns the cube root of a number. @@ -385,7 +385,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sin(self) -> f128 { - unsafe { intrinsics::sinf128(self) } + intrinsics::sinf128(self) } /// Computes the cosine of a number (in radians). @@ -414,7 +414,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cos(self) -> f128 { - unsafe { intrinsics::cosf128(self) } + intrinsics::cosf128(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs index 5599528717c..2565ef0f9f2 100644 --- a/library/std/src/num/f16.rs +++ b/library/std/src/num/f16.rs @@ -44,7 +44,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn powf(self, n: f16) -> f16 { - unsafe { intrinsics::powf16(self, n) } + intrinsics::powf16(self, n) } /// Returns `e^(self)`, (the exponential function). @@ -76,7 +76,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp(self) -> f16 { - unsafe { intrinsics::expf16(self) } + intrinsics::expf16(self) } /// Returns `2^(self)`. @@ -106,7 +106,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp2(self) -> f16 { - unsafe { intrinsics::exp2f16(self) } + intrinsics::exp2f16(self) } /// Returns the natural logarithm of the number. @@ -151,7 +151,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln(self) -> f16 { - unsafe { intrinsics::logf16(self) } + intrinsics::logf16(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -241,7 +241,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log2(self) -> f16 { - unsafe { intrinsics::log2f16(self) } + intrinsics::log2f16(self) } /// Returns the base 10 logarithm of the number. @@ -284,7 +284,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn log10(self) -> f16 { - unsafe { intrinsics::log10f16(self) } + intrinsics::log10f16(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -350,7 +350,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sin(self) -> f16 { - unsafe { intrinsics::sinf16(self) } + intrinsics::sinf16(self) } /// Computes the cosine of a number (in radians). @@ -379,7 +379,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cos(self) -> f16 { - unsafe { intrinsics::cosf16(self) } + intrinsics::cosf16(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index 0247080a8d6..ac1d889cc37 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -338,7 +338,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powf(self, n: f32) -> f32 { - unsafe { intrinsics::powf32(self, n) } + intrinsics::powf32(self, n) } /// Returns the square root of a number. @@ -395,7 +395,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f32 { - unsafe { intrinsics::expf32(self) } + intrinsics::expf32(self) } /// Returns `2^(self)`. @@ -420,7 +420,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f32 { - unsafe { intrinsics::exp2f32(self) } + intrinsics::exp2f32(self) } /// Returns the natural logarithm of the number. @@ -455,7 +455,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f32 { - unsafe { intrinsics::logf32(self) } + intrinsics::logf32(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -525,7 +525,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { - unsafe { intrinsics::log2f32(self) } + intrinsics::log2f32(self) } /// Returns the base 10 logarithm of the number. @@ -558,7 +558,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f32 { - unsafe { intrinsics::log10f32(self) } + intrinsics::log10f32(self) } /// The positive difference of two numbers. @@ -683,7 +683,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f32 { - unsafe { intrinsics::sinf32(self) } + intrinsics::sinf32(self) } /// Computes the cosine of a number (in radians). @@ -707,7 +707,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f32 { - unsafe { intrinsics::cosf32(self) } + intrinsics::cosf32(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index 1cfd3909d96..55c8593a0c0 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -338,7 +338,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn powf(self, n: f64) -> f64 { - unsafe { intrinsics::powf64(self, n) } + intrinsics::powf64(self, n) } /// Returns the square root of a number. @@ -395,7 +395,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp(self) -> f64 { - unsafe { intrinsics::expf64(self) } + intrinsics::expf64(self) } /// Returns `2^(self)`. @@ -420,7 +420,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp2(self) -> f64 { - unsafe { intrinsics::exp2f64(self) } + intrinsics::exp2f64(self) } /// Returns the natural logarithm of the number. @@ -455,7 +455,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln(self) -> f64 { - unsafe { intrinsics::logf64(self) } + intrinsics::logf64(self) } /// Returns the logarithm of the number with respect to an arbitrary base. @@ -525,7 +525,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { - unsafe { intrinsics::log2f64(self) } + intrinsics::log2f64(self) } /// Returns the base 10 logarithm of the number. @@ -558,7 +558,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log10(self) -> f64 { - unsafe { intrinsics::log10f64(self) } + intrinsics::log10f64(self) } /// The positive difference of two numbers. @@ -683,7 +683,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin(self) -> f64 { - unsafe { intrinsics::sinf64(self) } + intrinsics::sinf64(self) } /// Computes the cosine of a number (in radians). @@ -707,7 +707,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cos(self) -> f64 { - unsafe { intrinsics::cosf64(self) } + intrinsics::cosf64(self) } /// Computes the tangent of a number (in radians). diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 8b7282c51d1..b7be869c4eb 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -331,7 +331,7 @@ fn default_hook(info: &PanicHookInfo<'_>) { #[cfg(not(test))] #[doc(hidden)] -#[cfg(feature = "panic_immediate_abort")] +#[cfg(panic = "immediate-abort")] #[unstable(feature = "update_panic_count", issue = "none")] pub mod panic_count { /// A reason for forcing an immediate abort on panic. @@ -371,7 +371,7 @@ pub mod panic_count { #[cfg(not(test))] #[doc(hidden)] -#[cfg(not(feature = "panic_immediate_abort"))] +#[cfg(not(panic = "immediate-abort"))] #[unstable(feature = "update_panic_count", issue = "none")] pub mod panic_count { use crate::cell::Cell; @@ -499,13 +499,13 @@ pub mod panic_count { pub use realstd::rt::panic_count; /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. -#[cfg(feature = "panic_immediate_abort")] +#[cfg(panic = "immediate-abort")] pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> { Ok(f()) } /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. -#[cfg(not(feature = "panic_immediate_abort"))] +#[cfg(not(panic = "immediate-abort"))] pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> { union Data<F, R> { f: ManuallyDrop<F>, @@ -720,14 +720,14 @@ pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] #[cfg_attr(not(any(test, doctest)), lang = "begin_panic")] // lang item for CTFE panic support -// never inline unless panic_immediate_abort to avoid code +// never inline unless panic=immediate-abort to avoid code // bloat at the call sites as much as possible -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))] -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] #[rustc_do_not_const_check] // hooked by const-eval pub const fn begin_panic<M: Any + Send>(msg: M) -> ! { - if cfg!(feature = "panic_immediate_abort") { + if cfg!(panic = "immediate-abort") { intrinsics::abort() } @@ -861,7 +861,7 @@ fn panic_with_hook( /// This is the entry point for `resume_unwind`. /// It just forwards the payload to the panic runtime. -#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(panic = "immediate-abort", inline)] pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! { panic_count::increase(false); @@ -890,16 +890,14 @@ pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! { /// on which to slap yer breakpoints. #[inline(never)] #[cfg_attr(not(test), rustc_std_internal_symbol)] -#[cfg(not(feature = "panic_immediate_abort"))] +#[cfg(not(panic = "immediate-abort"))] fn rust_panic(msg: &mut dyn PanicPayload) -> ! { let code = unsafe { __rust_start_panic(msg) }; rtabort!("failed to initiate panic, error {code}") } #[cfg_attr(not(test), rustc_std_internal_symbol)] -#[cfg(feature = "panic_immediate_abort")] +#[cfg(panic = "immediate-abort")] fn rust_panic(_: &mut dyn PanicPayload) -> ! { - unsafe { - crate::intrinsics::abort(); - } + crate::intrinsics::abort(); } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 8d95cc1fb57..2717b7b469c 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -39,11 +39,11 @@ fn __rust_abort() { // - nothing (so this macro is a no-op) macro_rules! rtprintpanic { ($($t:tt)*) => { - #[cfg(not(feature = "panic_immediate_abort"))] + #[cfg(not(panic = "immediate-abort"))] if let Some(mut out) = crate::sys::stdio::panic_output() { let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*)); } - #[cfg(feature = "panic_immediate_abort")] + #[cfg(panic = "immediate-abort")] { let _ = format_args!($($t)*); } diff --git a/library/std/src/sync/nonpoison/mutex.rs b/library/std/src/sync/nonpoison/mutex.rs index 07430ce3a13..eeecf5d7107 100644 --- a/library/std/src/sync/nonpoison/mutex.rs +++ b/library/std/src/sync/nonpoison/mutex.rs @@ -373,7 +373,7 @@ impl<T: ?Sized> Mutex<T> { /// or written through after the mutex is dropped. #[unstable(feature = "mutex_data_ptr", issue = "140368")] // #[unstable(feature = "nonpoison_mutex", issue = "134645")] - pub fn data_ptr(&self) -> *mut T { + pub const fn data_ptr(&self) -> *mut T { self.data.get() } } diff --git a/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs index eb0aef99cc1..b2f26edc083 100644 --- a/library/std/src/sync/nonpoison/rwlock.rs +++ b/library/std/src/sync/nonpoison/rwlock.rs @@ -495,7 +495,7 @@ impl<T: ?Sized> RwLock<T> { /// or written through after the lock is dropped. #[unstable(feature = "rwlock_data_ptr", issue = "140368")] // #[unstable(feature = "nonpoison_rwlock", issue = "134645")] - pub fn data_ptr(&self) -> *mut T { + pub const fn data_ptr(&self) -> *mut T { self.data.get() } } diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 7e9d920d92f..6fdb4f6799e 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -668,7 +668,7 @@ impl<T: ?Sized> Mutex<T> { /// are properly synchronized to avoid data races, and that it is not read /// or written through after the mutex is dropped. #[unstable(feature = "mutex_data_ptr", issue = "140368")] - pub fn data_ptr(&self) -> *mut T { + pub const fn data_ptr(&self) -> *mut T { self.data.get() } } diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 0a463f3f9c7..e3a72c73bf4 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -667,7 +667,7 @@ impl<T: ?Sized> RwLock<T> { /// are properly synchronized to avoid data races, and that it is not read /// or written through after the lock is dropped. #[unstable(feature = "rwlock_data_ptr", issue = "140368")] - pub fn data_ptr(&self) -> *mut T { + pub const fn data_ptr(&self) -> *mut T { self.data.get() } } diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 4140718560c..f560b616dd9 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -355,7 +355,7 @@ impl<T: ?Sized> ReentrantLock<T> { /// properly synchronized to avoid data races, and that it is not read /// through after the lock is dropped. #[unstable(feature = "reentrant_lock_data_ptr", issue = "140368")] - pub fn data_ptr(&self) -> *const T { + pub const fn data_ptr(&self) -> *const T { &raw const self.data } diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index b50574de937..c0d69c3e002 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -92,6 +92,9 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff /// /// Queries a handle to determine if it supports a specified protocol. If the protocol is /// supported by the handle, it opens the protocol on behalf of the calling agent. +/// +/// The protocol is opened with the attribute GET_PROTOCOL, which means the caller is not required +/// to close the protocol interface with `EFI_BOOT_SERVICES.CloseProtocol()` pub(crate) fn open_protocol<T>( handle: NonNull<crate::ffi::c_void>, mut protocol_guid: Guid, @@ -473,6 +476,7 @@ impl<'a> crate::fmt::Debug for DevicePathNode<'a> { } } +/// Protocols installed by Rust side on a handle. pub(crate) struct OwnedProtocol<T> { guid: r_efi::efi::Guid, handle: NonNull<crate::ffi::c_void>, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 797feeb2bbb..0a6f2e5d508 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -230,7 +230,7 @@ impl fmt::Display for AccessError { impl Error for AccessError {} // This ensures the panicking code is outlined from `with` for `LocalKey`. -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(not(panic = "immediate-abort"), inline(never))] #[track_caller] #[cold] fn panic_access_error(err: AccessError) -> ! { diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 855261aaecf..63af53a8e74 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -10306,7 +10306,7 @@ pub fn vfmad_lane_f64<const LANE: i32>(a: f64, b: f64, c: float64x1_t) -> f64 { #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmah_f16(a: f16, b: f16, c: f16) -> f16 { - unsafe { fmaf16(b, c, a) } + fmaf16(b, c, a) } #[doc = "Floating-point fused multiply-add to accumulator"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vfmah_lane_f16)"] @@ -22448,7 +22448,7 @@ pub fn vrndaq_f64(a: float64x2_t) -> float64x2_t { #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinta))] pub fn vrndah_f16(a: f16) -> f16 { - unsafe { roundf16(a) } + roundf16(a) } #[doc = "Floating-point round to integral, to nearest with ties to away"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndh_f16)"] @@ -22458,7 +22458,7 @@ pub fn vrndah_f16(a: f16) -> f16 { #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintz))] pub fn vrndh_f16(a: f16) -> f16 { - unsafe { truncf16(a) } + truncf16(a) } #[doc = "Floating-point round to integral, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndi_f16)"] @@ -22639,7 +22639,7 @@ pub fn vrndmq_f64(a: float64x2_t) -> float64x2_t { #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintm))] pub fn vrndmh_f16(a: f16) -> f16 { - unsafe { floorf16(a) } + floorf16(a) } #[doc = "Floating-point round to integral, to nearest with ties to even"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndn_f64)"] @@ -22770,7 +22770,7 @@ pub fn vrndpq_f64(a: float64x2_t) -> float64x2_t { #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintp))] pub fn vrndph_f16(a: f16) -> f16 { - unsafe { ceilf16(a) } + ceilf16(a) } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndx_f16)"] @@ -24268,7 +24268,7 @@ pub fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fsqrt))] pub fn vsqrth_f16(a: f16) -> f16 { - unsafe { sqrtf16(a) } + sqrtf16(a) } #[doc = "Shift Right and Insert (immediate)"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vsri_n_s8)"] diff --git a/library/stdarch/crates/core_arch/src/wasm32/mod.rs b/library/stdarch/crates/core_arch/src/wasm32/mod.rs index 60049c73295..01bf0a71658 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/mod.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/mod.rs @@ -43,7 +43,7 @@ pub fn unreachable() -> ! { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f32_ceil(a: f32) -> f32 { - unsafe { crate::intrinsics::ceilf32(a) } + crate::intrinsics::ceilf32(a) } /// Generates the [`f32.floor`] instruction, returning the largest integer less than or equal to `a`. @@ -57,7 +57,7 @@ pub fn f32_ceil(a: f32) -> f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f32_floor(a: f32) -> f32 { - unsafe { crate::intrinsics::floorf32(a) } + crate::intrinsics::floorf32(a) } /// Generates the [`f32.trunc`] instruction, roundinging to the nearest integer towards zero. @@ -71,7 +71,7 @@ pub fn f32_floor(a: f32) -> f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f32_trunc(a: f32) -> f32 { - unsafe { crate::intrinsics::truncf32(a) } + crate::intrinsics::truncf32(a) } /// Generates the [`f32.nearest`] instruction, roundinging to the nearest integer. Rounds half-way @@ -100,7 +100,7 @@ pub fn f32_nearest(a: f32) -> f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f32_sqrt(a: f32) -> f32 { - unsafe { crate::intrinsics::sqrtf32(a) } + crate::intrinsics::sqrtf32(a) } /// Generates the [`f64.ceil`] instruction, returning the smallest integer greater than or equal to `a`. @@ -114,7 +114,7 @@ pub fn f32_sqrt(a: f32) -> f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f64_ceil(a: f64) -> f64 { - unsafe { crate::intrinsics::ceilf64(a) } + crate::intrinsics::ceilf64(a) } /// Generates the [`f64.floor`] instruction, returning the largest integer less than or equal to `a`. @@ -128,7 +128,7 @@ pub fn f64_ceil(a: f64) -> f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f64_floor(a: f64) -> f64 { - unsafe { crate::intrinsics::floorf64(a) } + crate::intrinsics::floorf64(a) } /// Generates the [`f64.trunc`] instruction, roundinging to the nearest integer towards zero. @@ -142,7 +142,7 @@ pub fn f64_floor(a: f64) -> f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f64_trunc(a: f64) -> f64 { - unsafe { crate::intrinsics::truncf64(a) } + crate::intrinsics::truncf64(a) } /// Generates the [`f64.nearest`] instruction, roundinging to the nearest integer. Rounds half-way @@ -171,7 +171,7 @@ pub fn f64_nearest(a: f64) -> f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "wasm_numeric_instr", issue = "133908")] pub fn f64_sqrt(a: f64) -> f64 { - unsafe { crate::intrinsics::sqrtf64(a) } + crate::intrinsics::sqrtf64(a) } unsafe extern "C-unwind" { diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index ccdcea980e1..34b330e1b85 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -3108,7 +3108,7 @@ intrinsics: types: - [f16, 'h_'] compose: - - FnCall: [roundf16, [a], [], true] + - FnCall: [roundf16, [a], []] - name: "vrndn{neon_type.no}" doc: "Floating-point round to integral, to nearest with ties to even" @@ -3208,7 +3208,7 @@ intrinsics: types: - [f16, 'h_'] compose: - - FnCall: [floorf16, [a], [], true] + - FnCall: [floorf16, [a], []] @@ -3257,7 +3257,7 @@ intrinsics: types: - [f16, 'h_'] compose: - - FnCall: [ceilf16, [a], [], true] + - FnCall: [ceilf16, [a], []] - name: "vrnd{neon_type.no}" doc: "Floating-point round to integral, toward zero" @@ -3304,7 +3304,7 @@ intrinsics: types: - [f16, 'h_'] compose: - - FnCall: [truncf16, [a], [], true] + - FnCall: [truncf16, [a], []] - name: "vrndi{neon_type.no}" @@ -8499,7 +8499,7 @@ intrinsics: types: - [f16, 'h_'] compose: - - FnCall: [sqrtf16, [a], [], true] + - FnCall: [sqrtf16, [a], []] - name: "vrsqrts{type[0]}" doc: "Floating-point reciprocal square root step" @@ -10464,7 +10464,7 @@ intrinsics: types: - ["f16", "h_f16"] compose: - - FnCall: [fmaf16, [b, c, a], [], true] + - FnCall: [fmaf16, [b, c, a], []] - name: "vfmah_lane{type[2]}" diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index 7b4aeed94e9..ee4aec61872 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -31,7 +31,6 @@ llvm-libunwind = ["std/llvm-libunwind"] system-llvm-libunwind = ["std/system-llvm-libunwind"] optimize_for_size = ["std/optimize_for_size"] panic-unwind = ["std/panic-unwind"] -panic_immediate_abort = ["std/panic_immediate_abort"] profiler = ["dep:profiler_builtins"] std_detect_file_io = ["std/std_detect_file_io"] std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 68202500d97..91d80c96e42 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -38,6 +38,7 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "aarch64_be-unknown-hermit", "aarch64_be-unknown-none-softfloat", + "x86_64-unknown-motor", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM @@ -239,6 +240,10 @@ than building it. continue; } + if target.contains("motor") { + continue; + } + // skip check for cross-targets if skip_target_sanity && target != &build.host_target { continue; diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile index 71de8f917fa..04b46226acf 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:25.10 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile index adbb1f03378..095624d6fb7 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:25.10 ARG DEBIAN_FRONTEND=noninteractive diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile index e6133fce83e..4b61fd94a6c 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:25.10 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/doc/book b/src/doc/book -Subproject 3e9dc46aa563ca0c53ec826c41b05f10c591592 +Subproject 33f1af40cc44dde7e3e892f7a508e6f427d2cbc diff --git a/src/doc/reference b/src/doc/reference -Subproject b3ce60628c6f55ab8ff3dba9f3d20203df1c0de +Subproject cc7247d8dfaef4c39000bb12c55c32ba5b5ba97 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject dd26bc8e726dc2e73534c8972d4dccd1bed7495 +Subproject 2c9b490d70e535cf166bf17feba59e594579843 diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index df2bac877b6..0dc9ce843e9 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -2f3f27bf79ec147fec9d2e7980605307a74067f4 +9f32ccf35fb877270bc44a86a126440f04d676d0 diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index a1612738537..249140956c0 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -108,6 +108,7 @@ - [Installation](./autodiff/installation.md) - [How to debug](./autodiff/debugging.md) - [Autodiff flags](./autodiff/flags.md) + - [Type Trees](./autodiff/type-trees.md) # Source Code Representation diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index f1a406a1c29..4f5733ae082 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -48,9 +48,9 @@ In addition, many of the ideas discussed throughout this guide are idealized des that are not fully realized yet. All this makes keeping this guide completely up to date on everything very hard! -The Guide itself is of course open-source as well, -and the sources can be found at the [GitHub repository]. -If you find any mistakes in the guide, please file an issue about it. +The guide itself is of course open source as well, +and the sources are hosted on [a GitHub repository]. +If you find any mistakes in the guide, please file an issue. Even better, open a PR with a correction! If you do contribute to the guide, @@ -105,7 +105,7 @@ You might also find the following sites useful: [cheatsheet]: https://bors.rust-lang.org/ [Miri]: https://github.com/rust-lang/miri [@bors]: https://github.com/bors -[GitHub repository]: https://github.com/rust-lang/rustc-dev-guide/ +[a GitHub repository]: https://github.com/rust-lang/rustc-dev-guide/ [rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle [Forge]: https://forge.rust-lang.org/ [compiler-team]: https://github.com/rust-lang/compiler-team/ diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 1837b59e850..21162f8ee7d 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -68,6 +68,7 @@ Term | Meaning <span id="rib">rib</span> | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md)) <span id="rpit">RPIT</span> | A return-position `impl Trait`. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-return-types)). <span id="rpitit">RPITIT</span> | A return-position `impl Trait` in trait. Unlike RPIT, this is desugared to a generic associated type (GAT). Introduced in [RFC 3425](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). ([see more](../return-position-impl-trait-in-trait.md)) +<span id="rustbuild">rustbuild</span> | A deprecated term for the part of bootstrap that is written in Rust <span id="scrutinee">scrutinee</span> | A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee. <span id="sess">`sess`</span> | The compiler _session_, which stores global data used throughout compilation <span id="side-tables">side tables</span> | Because the [AST](#ast) and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. diff --git a/src/doc/rustc-dev-guide/src/autodiff/type-trees.md b/src/doc/rustc-dev-guide/src/autodiff/type-trees.md new file mode 100644 index 00000000000..68cb78650b0 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/autodiff/type-trees.md @@ -0,0 +1,193 @@ +# TypeTrees for Autodiff + +## What are TypeTrees? +Memory layout descriptors for Enzyme. Tell Enzyme exactly how types are structured in memory so it can compute derivatives efficiently. + +## Structure +```rust +TypeTree(Vec<Type>) + +Type { + offset: isize, // byte offset (-1 = everywhere) + size: usize, // size in bytes + kind: Kind, // Float, Integer, Pointer, etc. + child: TypeTree // nested structure +} +``` + +## Example: `fn compute(x: &f32, data: &[f32]) -> f32` + +**Input 0: `x: &f32`** +```rust +TypeTree(vec![Type { + offset: -1, size: 8, kind: Pointer, + child: TypeTree(vec![Type { + offset: 0, size: 4, kind: Float, // Single value: use offset 0 + child: TypeTree::new() + }]) +}]) +``` + +**Input 1: `data: &[f32]`** +```rust +TypeTree(vec![Type { + offset: -1, size: 8, kind: Pointer, + child: TypeTree(vec![Type { + offset: -1, size: 4, kind: Float, // -1 = all elements + child: TypeTree::new() + }]) +}]) +``` + +**Output: `f32`** +```rust +TypeTree(vec![Type { + offset: 0, size: 4, kind: Float, // Single scalar: use offset 0 + child: TypeTree::new() +}]) +``` + +## Why Needed? +- Enzyme can't deduce complex type layouts from LLVM IR +- Prevents slow memory pattern analysis +- Enables correct derivative computation for nested structures +- Tells Enzyme which bytes are differentiable vs metadata + +## What Enzyme Does With This Information: + +Without TypeTrees: +```llvm +; Enzyme sees generic LLVM IR: +define float @distance(ptr %p1, ptr %p2) { +; Has to guess what these pointers point to +; Slow analysis of all memory operations +; May miss optimization opportunities +} +``` + +With TypeTrees: +```llvm +define "enzyme_type"="{[-1]:Float@float}" float @distance( + ptr "enzyme_type"="{[-1]:Pointer, [-1,0]:Float@float}" %p1, + ptr "enzyme_type"="{[-1]:Pointer, [-1,0]:Float@float}" %p2 +) { +; Enzyme knows exact type layout +; Can generate efficient derivative code directly +} +``` + +# TypeTrees - Offset and -1 Explained + +## Type Structure + +```rust +Type { + offset: isize, // WHERE this type starts + size: usize, // HOW BIG this type is + kind: Kind, // WHAT KIND of data (Float, Int, Pointer) + child: TypeTree // WHAT'S INSIDE (for pointers/containers) +} +``` + +## Offset Values + +### Regular Offset (0, 4, 8, etc.) +**Specific byte position within a structure** + +```rust +struct Point { + x: f32, // offset 0, size 4 + y: f32, // offset 4, size 4 + id: i32, // offset 8, size 4 +} +``` + +TypeTree for `&Point` (internal representation): +```rust +TypeTree(vec![ + Type { offset: 0, size: 4, kind: Float }, // x at byte 0 + Type { offset: 4, size: 4, kind: Float }, // y at byte 4 + Type { offset: 8, size: 4, kind: Integer } // id at byte 8 +]) +``` + +Generates LLVM +```llvm +"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer}" +``` + +### Offset -1 (Special: "Everywhere") +**Means "this pattern repeats for ALL elements"** + +#### Example 1: Direct Array `[f32; 100]` (no pointer indirection) +```rust +TypeTree(vec![Type { + offset: -1, // ALL positions + size: 4, // each f32 is 4 bytes + kind: Float, // every element is float +}]) +``` + +Generates LLVM: `"enzyme_type"="{[-1]:Float@float}"` + +#### Example 1b: Array Reference `&[f32; 100]` (with pointer indirection) +```rust +TypeTree(vec![Type { + offset: -1, size: 8, kind: Pointer, + child: TypeTree(vec![Type { + offset: -1, // ALL array elements + size: 4, // each f32 is 4 bytes + kind: Float, // every element is float + }]) +}]) +``` + +Generates LLVM: `"enzyme_type"="{[-1]:Pointer, [-1,-1]:Float@float}"` + +Instead of listing 100 separate Types with offsets `0,4,8,12...396` + +#### Example 2: Slice `&[i32]` +```rust +// Pointer to slice data +TypeTree(vec![Type { + offset: -1, size: 8, kind: Pointer, + child: TypeTree(vec![Type { + offset: -1, // ALL slice elements + size: 4, // each i32 is 4 bytes + kind: Integer + }]) +}]) +``` + +Generates LLVM: `"enzyme_type"="{[-1]:Pointer, [-1,-1]:Integer}"` + +#### Example 3: Mixed Structure +```rust +struct Container { + header: i64, // offset 0 + data: [f32; 1000], // offset 8, but elements use -1 +} +``` + +```rust +TypeTree(vec![ + Type { offset: 0, size: 8, kind: Integer }, // header + Type { offset: 8, size: 4000, kind: Pointer, + child: TypeTree(vec![Type { + offset: -1, size: 4, kind: Float // ALL array elements + }]) + } +]) +``` + +## Key Distinction: Single Values vs Arrays + +**Single Values** use offset `0` for precision: +- `&f32` has exactly one f32 value at offset 0 +- More precise than using -1 ("everywhere") +- Generates: `{[-1]:Pointer, [-1,0]:Float@float}` + +**Arrays** use offset `-1` for efficiency: +- `&[f32; 100]` has the same pattern repeated 100 times +- Using -1 avoids listing 100 separate offsets +- Generates: `{[-1]:Pointer, [-1,-1]:Float@float}` \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/writing-tools-in-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/writing-tools-in-bootstrap.md index c3660e24b15..8ac2e6bfe28 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/writing-tools-in-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/writing-tools-in-bootstrap.md @@ -3,18 +3,32 @@ There are three types of tools you can write in bootstrap: - **`Mode::ToolBootstrap`** + Use this for tools that don’t need anything from the in-tree compiler and can run with the stage0 `rustc`. - The output is placed in the "bootstrap-tools" directory. This mode is for general-purpose tools built - entirely with the stage0 compiler, including target libraries and only works for stage 0. + The output is placed in the "bootstrap-tools" directory. + This mode is for general-purpose tools built entirely with the stage0 compiler, + including target libraries, and it only works for stage 0. - **`Mode::ToolStd`** - Use this for tools that rely on the locally built std. The output goes into the "stageN-tools" directory. + + Use this for tools that rely on the locally built std. + The output goes into the "stageN-tools" directory. This mode is rarely used, mainly for `compiletest` which requires `libtest`. - **`Mode::ToolRustcPrivate`** - Use this for tools that use the `rustc_private` mechanism, and thus depend on the locally built `rustc` and its rlib artifacts. This is more complex than the other modes because the tool must be built with the same compiler used for `rustc` and placed in the "stageN-tools" directory. When you choose `Mode::ToolRustcPrivate`, `ToolBuild` implementation takes care of this automatically. If you need to use the builder’s compiler for something specific, you can get it from `ToolBuildResult`, which is - returned by the tool's [`Step`]. -Regardless of the tool type you must return `ToolBuildResult` from the tool’s [`Step`] implementation and use `ToolBuild` inside it. + Use this for tools that use the `rustc_private` mechanism, + and thus depend on the locally built `rustc` and its rlib artifacts. + This is more complex than the other modes, + because the tool must be built with the same compiler used for `rustc`, + and placed in the "stageN-tools" directory. + When you choose `Mode::ToolRustcPrivate`, + `ToolBuild` implementation takes care of this automatically. + If you need to use the builder’s compiler for something specific, + you can get it from `ToolBuildResult`, which is returned by the tool's [`Step`]. + +Regardless of the tool type, +you must return `ToolBuildResult` from the tool’s [`Step`] implementation, +and use `ToolBuild` inside it. [`Step`]: https://doc.rust-lang.org/nightly/nightly-rustc/bootstrap/core/builder/trait.Step.html diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index b07d3533f59..36610f28854 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -149,7 +149,7 @@ On Windows, the Powershell commands may give you an error that looks like this: ``` PS C:\Users\vboxuser\rust> ./x ./x : File C:\Users\vboxuser\rust\x.ps1 cannot be loaded because running scripts is disabled on this system. For more -information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. +information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170. At line:1 char:1 + ./x + ~~~ diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index 6be52833f39..896d9e6f6d9 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -1,10 +1,14 @@ # About the compiler team +> NOTE: +> There exists much detail about the team [on Forge], making most of the following obsolete. + rustc is maintained by the [Rust compiler team][team]. The people who belong to this team collectively work to track regressions and implement new features. Members of the Rust compiler team are people who have made significant contributions to rustc and its design. +[on Forge]: https://forge.rust-lang.org/compiler [team]: https://www.rust-lang.org/governance/teams/compiler ## Discussion diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md index 30005378617..cc98b49a97c 100644 --- a/src/doc/rustc-dev-guide/src/fuzzing.md +++ b/src/doc/rustc-dev-guide/src/fuzzing.md @@ -90,14 +90,15 @@ Here are a few things you can do to help the Rust project after filing an ICE. triggering the ICE, such as syntax errors or borrow-checking errors - Minimize the test case (see below). If successful, you can label the issue with `S-has-mcve`. Otherwise, you can apply `E-needs-mcve`. -- Add the minimal test case to the rust-lang/rust repo as a [crashes test]. +- Add the minimal test case to the rust-lang/rust repo as a [crash test]. While you're at it, consider including other "untracked" crashes in your PR. - Please don't forget to mark your issue with `S-bug-has-test` afterwards. + Please don't forget to mark all relevant issues with `S-bug-has-test` once + your PR is merged. See also [applying and removing labels][labeling]. [bisect]: https://rust-lang.github.io/cargo-bisect-rustc/ -[crashes test]: tests/compiletest.html#crashes-tests +[crash test]: tests/compiletest.html#crash-tests [labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels ## Minimization diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index 0d4f23bcd9a..e452dde5226 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -4,8 +4,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or ## Initial steps -- Get a clean checkout of rust-lang/master, or whatever it is you want - to profile. +- Get a clean checkout of rust-lang/rust - Set the following settings in your `bootstrap.toml`: - `rust.debuginfo-level = 1` - enables line debuginfo - `rust.jemalloc = false` - lets you do memory use profiling with valgrind diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index efc626035b7..10372c36ac9 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -71,7 +71,7 @@ related tests. > //! Regression test for <https://github.com/rust-lang/rust/issues/123456>. > ``` > -> One exception to this rule is [crashes tests]: there it is canonical that +> One exception to this rule is [crash tests]: there it is canonical that > tests are named only after issue numbers because its purpose is to track > snippets from which issues no longer ICE/crash, and they would either be > removed or converted into proper ui/other tests in the fix PRs. @@ -199,4 +199,4 @@ See [LLVM FileCheck guide][FileCheck] for details. [compiletest directives]: ./directives.md [`run-make`]: ./compiletest.md#run-make-tests [FileCheck]: https://llvm.org/docs/CommandGuide/FileCheck.html -[crashes tests]: ./compiletest.md#crashes-tests +[crash tests]: ./compiletest.md#crash-tests diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index a8cc959124f..6c0b5c2e845 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -1,18 +1,18 @@ # Testing with CI The primary goal of our CI system is to ensure that the `master` branch of -`rust-lang/rust` is always in a valid state and passes our test suite. +`rust-lang/rust` is always in a valid state by passing our test suite. From a high-level point of view, when you open a pull request at `rust-lang/rust`, the following will happen: - A small [subset](#pull-request-builds) of tests and checks are run after each - push to the PR. This should help catching common errors. + push to the PR. This should help catch common errors. - When the PR is approved, the [bors] bot enqueues the PR into a [merge queue]. - Once the PR gets to the front of the queue, bors will create a merge commit and run the [full test suite](#auto-builds) on it. The merge commit either contains only one specific PR or it can be a ["rollup"](#rollups) which - combines multiple PRs together, to save CI costs. + combines multiple PRs together, to reduce CI costs and merge delays. - Once the whole test suite finishes, two things can happen. Either CI fails with an error that needs to be addressed by the developer, or CI succeeds and the merge commit is then pushed to the `master` branch. @@ -38,12 +38,12 @@ input, which contains a declarative configuration of all our CI jobs. > orchestrating the scripts that drive the process. In essence, all CI jobs run `./x test`, `./x dist` or some other command with -different configurations, across various operating systems, targets and +different configurations, across various operating systems, targets, and platforms. There are two broad categories of jobs that are executed, `dist` and non-`dist` jobs. - Dist jobs build a full release of the compiler for a specific platform, - including all the tools we ship through rustup; Those builds are then uploaded + including all the tools we ship through rustup. Those builds are then uploaded to the `rust-lang-ci2` S3 bucket and are available to be locally installed with the [rustup-toolchain-install-master] tool. The same builds are also used for actual releases: our release process basically consists of copying those @@ -70,7 +70,7 @@ these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `pr-check-1`, `pr-che and `tidy` jobs, all running on Linux. These execute a relatively short (~40 minutes) and lightweight test suite that should catch common issues. More specifically, they run a set of lints, they try to perform a cross-compile check -build to Windows mingw (without producing any artifacts) and they test the +build to Windows mingw (without producing any artifacts), and they test the compiler using a *system* version of LLVM. Unfortunately, it would take too many resources to run the full test suite for each commit on every PR. @@ -95,17 +95,16 @@ jobs that exercise various tests across operating systems and targets. The full test suite is quite slow; it can take several hours until all the `auto` CI jobs finish. -Most platforms only run the build steps, some run a restricted set of tests, +Most platforms only run the build steps, some run a restricted set of tests; only a subset run the full suite of tests (see Rust's [platform tiers]). Auto jobs are defined in the `auto` section of [`jobs.yml`]. They are executed -on the `auto` branch under the `rust-lang/rust` repository and -their results can be seen [here](https://github.com/rust-lang/rust/actions), -although usually you will be notified of the result by a comment made by bors on -the corresponding PR. +on the `auto` branch under the `rust-lang/rust` repository, +and the final result will be reported via a comment made by bors on the corresponding PR. +The live results can be seen on [the GitHub Actions workflows page]. At any given time, at most a single `auto` build is being executed. Find out -more [here](#merging-prs-serially-with-bors). +more in [Merging PRs serially with bors](#merging-prs-serially-with-bors). [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support @@ -125,7 +124,7 @@ There are several use-cases for try builds: when you start a try build). To create a try build and schedule it for a performance benchmark, you can use the `@bors try @rust-timer queue` command combination. -- Check the impact of the PR across the Rust ecosystem, using a [crater] run. +- Check the impact of the PR across the Rust ecosystem, using a [Crater](crater.md) run. Again, a working compiler build is needed for this, which can be produced by the [dist-x86_64-linux] CI job. - Run a specific CI job (e.g. Windows tests) on a PR, to quickly test if it @@ -134,11 +133,11 @@ There are several use-cases for try builds: By default, if you send a comment with `@bors try`, the jobs defined in the `try` section of [`jobs.yml`] will be executed. We call this mode a "fast try build". Such a try build will not execute any tests, and it will allow compilation warnings. It is useful when you want to -get an optimized toolchain as fast as possible, for a crater run or performance benchmarks, +get an optimized toolchain as fast as possible, for a Crater run or performance benchmarks, even if it might not be working fully correctly. If you want to do a full build for the default try job, specify its job name in a job pattern (explained below). -If you want to run custom CI job(s) in a try build and make sure that they pass all tests and do +If you want to run custom CI jobs in a try build and make sure that they pass all tests and do not produce any compilation warnings, you can select CI jobs to be executed by specifying a *job pattern*, which can be used in one of two ways: - You can add a set of `try-job: <job pattern>` directives to the PR description (described below) and then @@ -151,8 +150,9 @@ which can be used in one of two ways: Each job pattern can either be an exact name of a job or a glob pattern that matches multiple jobs, for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try build. When using -glob patterns, you might want to wrap them in backticks (`` ` ``) to avoid GitHub rendering -the pattern as Markdown. +glob patterns in the PR description, you can optionally wrap them in backticks (`` ` ``) to avoid GitHub rendering +the pattern as Markdown if it contains e.g. an asterisk. Note that this escaping will not work when using +the `@bors jobs=` parameter. The job pattern needs to match one or more jobs defined in the `auto` or `optional` sections of [`jobs.yml`]: @@ -189,18 +189,17 @@ of [`jobs.yml`]: > that are exercised this way. Try builds are executed on the `try` branch under the `rust-lang/rust` repository and -their results can be seen [here](https://github.com/rust-lang/rust/actions), +their results can be seen on [the GitHub Actions workflows page], although usually you will be notified of the result by a comment made by bors on the corresponding PR. Multiple try builds can execute concurrently across different PRs, but there can be at most a single try build running on a single PR at any given time. -Note that try builds are handled using the new [bors][new-bors] implementation. +Note that try builds are handled using the [new bors] implementation. [rustc-perf]: https://github.com/rust-lang/rustc-perf -[crater]: https://github.com/rust-lang/crater -[new-bors]: https://github.com/rust-lang/bors +[new bors]: https://github.com/rust-lang/bors ### Modifying CI jobs @@ -210,8 +209,7 @@ If you want to modify what gets executed on our CI, you can simply modify the You can also modify what gets executed temporarily, for example to test a particular platform or configuration that is challenging to test locally (for example, if a Windows build fails, but you don't have access to a Windows -machine). Don't hesitate to use CI resources in such situations to try out a -fix! +machine). Don't hesitate to use CI resources in such situations. You can perform an arbitrary CI job in two ways: - Use the [try build](#try-builds) functionality, and specify the CI jobs that @@ -254,8 +252,8 @@ purposes. </div> Although you are welcome to use CI, just be conscious that this is a shared -resource with limited concurrency. Try not to enable too many jobs at once (one -or two should be sufficient in most cases). +resource with limited concurrency. Try not to enable too many jobs at once; +one or two should be sufficient in most cases. ## Merging PRs serially with bors @@ -279,12 +277,12 @@ by listening for either Commit Statuses or Check Runs. Since the merge commit is based on the latest `master` and only one can be tested at the same time, when the results are green, `master` is fast-forwarded to that merge commit. -Unfortunately testing a single PR at the time, combined with our long CI (~2 -hours for a full run), means we can’t merge too many PRs in a single day, and a -single failure greatly impacts our throughput for the day. The maximum number of +Unfortunately, testing a single PR at a time, combined with our long CI (~2 +hours for a full run), means we can’t merge a lot of PRs in a single day, and a +single failure greatly impacts our throughput. The maximum number of PRs we can merge in a day is around ~10. -The large CI run times and requirement for a large builder pool is largely due +The long CI run times, and requirement for a large builder pool, is largely due to the fact that full release artifacts are built in the `dist-` builders. This is worth it because these release artifacts: @@ -297,12 +295,11 @@ is worth it because these release artifacts: Some PRs don’t need the full test suite to be executed: trivial changes like typo fixes or README improvements *shouldn’t* break the build, and testing every -single one of them for 2+ hours is a big waste of time. To solve this, we +single one of them for 2+ hours would be wasteful. To solve this, we regularly create a "rollup", a PR where we merge several pending trivial PRs so they can be tested together. Rollups are created manually by a team member using the "create a rollup" button on the [merge queue]. The team member uses their -judgment to decide if a PR is risky or not, and are the best tool we have at the -moment to keep the queue in a manageable state. +judgment to decide if a PR is risky or not. ## Docker @@ -315,18 +312,22 @@ platform’s custom [Docker container]. This has a lot of advantages for us: - We can use ancient build environments to ensure maximum binary compatibility, for example [using older CentOS releases][dist-x86_64-linux] on our Linux builders. -- We can avoid reinstalling tools (like QEMU or the Android emulator) every time +- We can avoid reinstalling tools (like QEMU or the Android emulator) every time, thanks to Docker image caching. -- Users can run the same tests in the same environment locally by just running - `cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>`, which is awesome to debug failures. Note that there are only linux docker images available locally due to licensing and +- Users can run the same tests in the same environment locally by just running this command: + + cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name> + + This is helpful for debugging failures. + Note that there are only Linux Docker images available locally due to licensing and other restrictions. -The docker images prefixed with `dist-` are used for building artifacts while +The Docker images prefixed with `dist-` are used for building artifacts while those without that prefix run tests and checks. We also run tests for less common architectures (mainly Tier 2 and Tier 3 -platforms) in CI. Since those platforms are not x86 we either run everything -inside QEMU or just cross-compile if we don’t want to run the tests for that +platforms) in CI. Since those platforms are not x86, we either run everything +inside QEMU, or we just cross-compile if we don’t want to run the tests for that platform. These builders are running on a special pool of builders set up and maintained @@ -363,41 +364,41 @@ invalidated if one of the following changes: [ghcr.io]: https://github.com/rust-lang/rust/pkgs/container/rust-ci [Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/ -### LLVM caching with sccache +### LLVM caching with Sccache -We build some C/C++ stuff in various CI jobs, and we rely on [sccache] to cache +We build some C/C++ stuff in various CI jobs, and we rely on [Sccache] to cache the intermediate LLVM artifacts. Sccache is a distributed ccache developed by Mozilla, which can use an object storage bucket as the storage backend. -With sccache there's no need to calculate the hash key ourselves. Sccache +With Sccache there's no need to calculate the hash key ourselves. Sccache invalidates the cache automatically when it detects changes to relevant inputs, such as the source code, the version of the compiler, and important environment variables. -So we just pass the sccache wrapper on top of cargo and sccache does the rest. +So we just pass the Sccache wrapper on top of Cargo and Sccache does the rest. -We store the persistent artifacts on the S3 bucket `rust-lang-ci-sccache2`. So -when the CI runs, if sccache sees that LLVM is being compiled with the same C/C++ -compiler and the LLVM source code is the same, sccache retrieves the individual +We store the persistent artifacts on the S3 bucket, `rust-lang-ci-sccache2`. So +when the CI runs, if Sccache sees that LLVM is being compiled with the same C/C++ +compiler and the LLVM source code is the same, Sccache retrieves the individual compiled translation units from S3. [sccache]: https://github.com/mozilla/sccache ## Custom tooling around CI -During the years we developed some custom tooling to improve our CI experience. +During the years, we developed some custom tooling to improve our CI experience. ### Rust Log Analyzer to show the error message in PRs The build logs for `rust-lang/rust` are huge, and it’s not practical to find -what caused the build to fail by looking at the logs. To improve the developers’ -experience we developed a bot called [Rust Log Analyzer][rla] (RLA) that -receives the build logs on failure and extracts the error message automatically, -posting it on the PR. +what caused the build to fail by looking at the logs. +We therefore developed a bot called [Rust Log Analyzer][rla] (RLA) that +receives the build logs on failure, and extracts the error message automatically, +posting it on the PR thread. The bot is not hardcoded to look for error strings, but was trained with a bunch of build failures to recognize which lines are common between builds and which are not. While the generated snippets can be weird sometimes, the bot is pretty -good at identifying the relevant lines even if it’s an error we've never seen +good at identifying the relevant lines, even if it’s an error we've never seen before. [rla]: https://github.com/rust-lang/rust-log-analyzer @@ -429,11 +430,11 @@ More information is available in the [toolstate documentation]. ## Public CI dashboard -To monitor the Rust CI, you can have a look at the [public dashboard] maintained by the infra-team. +To monitor the Rust CI, you can have a look at the [public dashboard] maintained by the infra team. These are some useful panels from the dashboard: -- Pipeline duration: check how long the auto builds takes to run. +- Pipeline duration: check how long the auto builds take to run. - Top slowest jobs: check which jobs are taking the longest to run. - Change in median job duration: check what jobs are slowest than before. Useful to detect regressions. @@ -456,8 +457,7 @@ this: 2. Choose the job you are interested in on the left-hand side. 3. Click on the gear icon and choose "View raw logs" 4. Search for the string "Configure the build" -5. All of the build settings are listed below that starting with the - `configure:` prefix. +5. All of the build settings are listed on the line with the text, `build.configure-args` [GitHub Actions]: https://github.com/rust-lang/rust/actions [`jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml @@ -467,3 +467,4 @@ this: [homu]: https://github.com/rust-lang/homu [merge queue]: https://bors.rust-lang.org/queue/rust [dist-x86_64-linux]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +[the GitHub Actions workflows page]: https://github.com/rust-lang/rust/actions diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md index 4caf4c0e0ee..74dbfb7d31b 100644 --- a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md @@ -1,3 +1,56 @@ -# GCC codegen backend tests +# GCC codegen backend -TODO: please add some more information to this page. +If you ran into an error related to tests executed with the GCC codegen backend on CI, +you can use the following command to run tests locally using the GCC backend: + +```bash +./x test tests/ui --set 'rust.codegen-backends = ["llvm", "gcc"]' --test-codegen-backend gcc +``` + +Below, you can find more information about how to configure the GCC backend in bootstrap. + +## Choosing which codegen backends are built + +The `rust.codegen-backends = [...]` bootstrap option affects which codegen backends will be built and +included in the sysroot of the produced `rustc`. To use the GCC codegen backend, `"gcc"` has to +be included in this array in `bootstrap.toml`: + +```toml +rust.codegen-backends = ["llvm", "gcc"] +``` + +If you don't want to change your `bootstrap.toml` file, you can alternatively run your `x` +commands with `--set rust.codegen-backends=["llvm", "gcc"]'`. For example: + +```bash +./x build --set 'rust.codegen-backends=["llvm", "gcc"]' +``` + +The first backend in the `codegen-backends` array will determine which backend will be used as the +*default backend* of the built `rustc`. This also determines which backend will be used to compile the +stage 1 standard library (or anything built in stage 2+). To produce `rustc` that uses the GCC backend +by default, you can thus put `"gcc"` as the first element of this array: + +```bash +./x build --set 'rust.codegen-backends=["gcc"]' library +``` + +## Choosing the codegen backend used in tests + +To run compiler tests with the GCC codegen backend being used to build the test Rust programs, you can use the +`--test-codegen-backend` flag: + +```bash +./x test tests/ui --test-codegen-backend gcc +``` + +Note that in order for this to work, the tested compiler must have the GCC codegen backend available in its sysroot +directory. You can achieve that using the [instructions above](#choosing-which-codegen-backends-are-built). + +## Downloading GCC from CI + +The `gcc.download-ci-gcc` bootstrap option controls if GCC (which is a dependency of the GCC codegen backend) +will be downloaded from CI or built locally. The default value is `true`, which will download GCC from CI +if there are no local changes to the GCC sources and the given host target is available on CI. + +Note that GCC can currently only be downloaded from CI for the `x86_64-unknown-linux-gnu` target. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index a4a729935fa..0234b394c2a 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -72,7 +72,7 @@ The following test suites are available, with links for more information: | [`mir-opt`](#mir-opt-tests) | Check MIR generation and optimizations | | [`coverage`](#coverage-tests) | Check coverage instrumentation | | [`coverage-run-rustdoc`](#coverage-tests) | `coverage` tests that also run instrumented doctests | -| [`crashes`](#crashes-tests) | Check that the compiler ICEs/panics/crashes on certain inputs to catch accidental fixes | +| [`crashes`](#crash-tests) | Check that the compiler ICEs/panics/crashes on certain inputs to catch accidental fixes | ### General purpose test suite @@ -557,7 +557,7 @@ only running the main `coverage` suite. [`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump [`tests/coverage-run-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-run-rustdoc -### Crashes tests +### Crash tests [`tests/crashes`] serve as a collection of tests that are expected to cause the compiler to ICE, panic or crash in some other way, so that accidental fixes are @@ -580,13 +580,13 @@ recommended to include test cases from several issues in a single PR. When you do so, each issue number should be noted in the file name (`12345.rs` should suffice) and also inside the file by means of a `//@ known-bug: #12345` directive. Please [label][labeling] the relevant issues with `S-bug-has-test` -afterwards. +once your PR is merged. If you happen to fix one of the crashes, please move it to a fitting subdirectory in `tests/ui` and give it a meaningful name. Please add a doc comment at the top of the file explaining why this test exists, even better if you can briefly explain how the example causes rustc to crash previously and -what was done to prevent rustc to ICE/panic/crash. +what was done to prevent rustc to ICE / panic / crash. Adding diff --git a/src/doc/rustc-dev-guide/src/tests/crater.md b/src/doc/rustc-dev-guide/src/tests/crater.md index 9d4ac87daf3..96bb5a4f2ae 100644 --- a/src/doc/rustc-dev-guide/src/tests/crater.md +++ b/src/doc/rustc-dev-guide/src/tests/crater.md @@ -8,30 +8,30 @@ stable compiler versions. ## When to run Crater -You should request a crater run if your PR makes large changes to the compiler +You should request a Crater run if your PR makes large changes to the compiler or could cause breakage. If you are unsure, feel free to ask your PR's reviewer. ## Requesting Crater Runs -The rust team maintains a few machines that can be used for running crater runs -on the changes introduced by a PR. If your PR needs a crater run, leave a +The Rust team maintains a few machines that can be used for Crater runs +on the changes introduced by a PR. If your PR needs a Crater run, leave a comment for the triage team in the PR thread. Please inform the team whether you -require a "check-only" crater run, a "build only" crater run, or a -"build-and-test" crater run. The difference is primarily in time; the -conservative (if you're not sure) option is to go for the build-and-test run. If +require a "check-only" Crater run, a "build only" Crater run, or a +"build-and-test" Crater run. The difference is primarily in time; +if you're not sure, go for the build-and-test run. If making changes that will only have an effect at compile-time (e.g., implementing -a new trait) then you only need a check run. +a new trait), then you only need a check run. Your PR will be enqueued by the triage team and the results will be posted when -they are ready. Check runs will take around ~3-4 days, with the other two taking +they are ready. Check runs will take around ~3-4 days, and the other two taking 5-6 days on average. -While crater is really useful, it is also important to be aware of a few +While Crater is really useful, it is also important to be aware of a few caveats: - Not all code is on crates.io! There is a lot of code in repos on GitHub and elsewhere. Also, companies may not wish to publish their code. Thus, a - successful crater run is not a magically green light that there will be no + successful Crater run does not mean there will be no breakage; you still need to be careful. - Crater only runs Linux builds on x86_64. Thus, other architectures and @@ -41,5 +41,5 @@ caveats: the crate doesn't compile any more (e.g. used old nightly features), has broken or flaky tests, requires network access, or other reasons. -- Before crater can be run, `@bors try` needs to succeed in building artifacts. - This means that if your code doesn't compile, you cannot run crater. +- Before Crater can be run, `@bors try` needs to succeed in building artifacts. + This means that if your code doesn't compile, you cannot run Crater. diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 5e5b81fc65b..a7cdab73e79 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -109,7 +109,7 @@ Miri, use `MIRI_LOG` instead. You get the idea :) See the [`tracing`] crate's docs, and specifically the docs for [`debug!`] to see the full syntax you can use. (Note: unlike the compiler, the [`tracing`] -crate and its examples use the `RUST_LOG` environment variable. rustc, rustdoc, +crate and its examples use the `RUSTC_LOG` environment variable. rustc, rustdoc, and other tools set custom environment variables.) **Note that unless you use a very strict filter, the logger will emit a lot of diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 445b10188e3..0e340de4daa 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -471,11 +471,13 @@ If not specified, overflow checks are enabled if This option lets you control what happens when the code panics. * `abort`: terminate the process upon panic +* `immediate-abort`: terminate the process upon panic, and do not call any panic hooks * `unwind`: unwind the stack upon panic If not specified, the default depends on the target. If any crate in the crate graph uses `abort`, the final binary (`bin`, `dylib`, `cdylib`, `staticlib`) must also use `abort`. +If any crate in the crate graph uses `immediate-abort`, every crate in the graph must use `immediate-abort`. If `std` is used as a `dylib` with `unwind`, the final binary must also use `unwind`. ## passes diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index ab95aa2e5a1..32e712a48d7 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -144,7 +144,7 @@ def minor_version(version): INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"] subprocess.run(INSTALL_TOOLCHAIN + ["nightly"]) -LOWER_BOUND = 73 +LOWER_BOUND = 87 NIGHTLY_VERSION = minor_version(subprocess.run( ["rustc", "+nightly", "--version"], capture_output=True, @@ -201,6 +201,9 @@ The following table shows known good combinations of toolchain versions. | 1.65 - 1.69 | 15 | | 1.70 - 1.72 | 16 | | 1.73 - 1.77 | 17 | -| 1.78 | 18 | +| 1.78 - 1.81 | 18 | +| 1.82 - 1.86 | 19 | +| 1.87 - 1.90 | 20 | +| 1.91 - 1.92 | 21 | Note that the compatibility policy for this feature might change in the future. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index e5e46f72637..99c8e365f5c 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -431,6 +431,7 @@ target | std | host | notes `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc [`x86_64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | x86_64 Managarm +[`x86_64-unknown-motor`[(platform-support/motor.md) | ? | | x86_64 Motor OS [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD [`x86_64-unknown-trusty`](platform-support/trusty.md) | ✓ | | `x86_64-uwp-windows-gnu` | ✓ | | diff --git a/src/doc/rustc/src/platform-support/motor.md b/src/doc/rustc/src/platform-support/motor.md new file mode 100644 index 00000000000..e7aa7b23f3a --- /dev/null +++ b/src/doc/rustc/src/platform-support/motor.md @@ -0,0 +1,45 @@ +# `x86_64-unknown-motor` + +**Tier: 3** + +[Motor OS](https://github.com/moturus/motor-os) is a new operating system +for virtualized environments. + +## Target maintainers + +[@lasiotus](https://github.com/lasiotus) + +## Requirements + +This target is cross-compiled. There are no special requirements for the host. + +Motor OS uses the ELF file format. + +## Building the target + +The target can be built by enabling it for a `rustc` build, for example: + +```toml +[build] +build-stage = 2 +target = ["x86_64-unknown-motor"] +``` + +## Building Rust programs + +Rust standard library is fully supported/implemented, but is not yet part of +the official Rust repo, so an out-of-tree building process should be +followed, as described in the +[build doc](https://github.com/moturus/motor-os/blob/main/docs/build.md). + +## Testing + +Cross-compiled Rust binaries and test artifacts can be executed in Motor OS VMs, +as described in e.g. +[Hello Motor OS](https://github.com/moturus/motor-os/blob/main/docs/recipes/hello-motor-os.md) +example. + +## Cross-compilation toolchains and C code + +C code can be compiled as part of Rust cargo projects. However, there is +no libc support. diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md index f0cc44a07f3..c15567dcac2 100644 --- a/src/doc/unstable-book/src/compiler-flags/branch-protection.md +++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md @@ -13,6 +13,7 @@ It takes some combination of the following values, separated by a `,`. - `leaf` - Enable pointer authentication for all functions, including leaf functions. - `b-key` - Sign return addresses with key B, instead of the default key A. - `bti` - Enable branch target identification. +- `gcs` - Enable guarded control stack support. `leaf`, `b-key` and `pc` are only valid if `pac-ret` was previously specified. For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 75febd6f737..3ea9de381ec 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -2227,11 +2227,18 @@ function preLoadCss(cssUrl) { }); }()); -// This section is a bugfix for firefox: when copying text with `user-select: none`, it adds -// extra backline characters. + +// Workaround for browser-specific bugs when copying code snippets. +// +// * In Firefox, copying text that includes elements with `user-select: none` +// inserts extra blank lines. +// - Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836 +// - Rust issue: https://github.com/rust-lang/rust/issues/141464 // -// Rustdoc issue: Workaround for https://github.com/rust-lang/rust/issues/141464 -// Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836 +// * In Chromium-based browsers, `document.getSelection()` includes elements +// with `user-select: none`, causing unwanted line numbers to be copied. +// - Chromium issue: https://issues.chromium.org/issues/446539520 +// - Rust issue: https://github.com/rust-lang/rust/issues/146816 (function() { document.body.addEventListener("copy", event => { let target = nonnull(event.target); @@ -2248,9 +2255,13 @@ function preLoadCss(cssUrl) { if (!isInsideCode) { return; } - const selection = document.getSelection(); - // @ts-expect-error - nonnull(event.clipboardData).setData("text/plain", selection.toString()); + const selection = nonnull(document.getSelection()); + const text = Array.from({ length: selection.rangeCount }, (_, i) => { + const fragment = selection.getRangeAt(i).cloneContents(); + fragment.querySelectorAll("[data-nosnippet]").forEach(el => el.remove()); + return fragment.textContent; + }).join(""); + nonnull(event.clipboardData).setData("text/plain", text); event.preventDefault(); }); }()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0ff1c090689..5d8f8f4bed1 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -836,8 +836,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { config::InputMode::NoInputMergeFinalize => { return wrap_return( dcx, - run_merge_finalize(render_options) - .map_err(|e| format!("could not write merged cross-crate info: {e}")), + rustc_span::create_session_globals_then(options.edition, &[], None, || { + run_merge_finalize(render_options) + .map_err(|e| format!("could not write merged cross-crate info: {e}")) + }), ); } }; diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index da09117b1bb..136ff258048 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -364,6 +364,7 @@ impl TagParser { } else { if !self.tag_name.is_empty() { self.in_attrs = true; + // range of the entire tag within dox let mut r = Range { start: range.start + start_pos, end: range.start + pos }; if c == '>' { // In case we have a tag without attribute, we can consider the span to @@ -381,7 +382,7 @@ impl TagParser { for (new_pos, c) in text[pos..].char_indices() { if !c.is_whitespace() { if c == '>' { - r.end = range.start + new_pos + 1; + r.end = range.start + pos + new_pos + 1; found = true; } else if c == '<' { self.handle_lt_in_tag(range.clone(), pos + new_pos, f); diff --git a/src/llvm-project b/src/llvm-project -Subproject 333793696b0a08002acac6af983adc7a5233fc5 +Subproject 8c30b9c5098bdff1d3d9a2d460ee091cd1171e6 diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index cdada5a2230..6597c3c70f6 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -12,7 +12,7 @@ path = "src/bin/main.rs" [dependencies] # tidy-alphabetical-start -anstyle-svg = "0.1.3" +anstyle-svg = "0.1.11" build_helper = { path = "../../build_helper" } camino = "1" colored = "2" diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 1277fd225eb..e84a2278766 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -201,6 +201,8 @@ pub struct TestProps { /// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios /// that don't otherwise want/need `-Z build-std`. pub add_core_stubs: bool, + /// Add these flags to the build of `minicore`. + pub core_stubs_compile_flags: Vec<String>, /// Whether line annotatins are required for the given error kind. pub dont_require_annotations: HashSet<ErrorKind>, /// Whether pretty printers should be disabled in gdb. @@ -253,6 +255,7 @@ mod directives { pub const FILECHECK_FLAGS: &'static str = "filecheck-flags"; pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg"; pub const ADD_CORE_STUBS: &'static str = "add-core-stubs"; + pub const CORE_STUBS_COMPILE_FLAGS: &'static str = "core-stubs-compile-flags"; // This isn't a real directive, just one that is probably mistyped often pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags"; pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers"; @@ -311,6 +314,7 @@ impl TestProps { no_auto_check_cfg: false, has_enzyme: false, add_core_stubs: false, + core_stubs_compile_flags: vec![], dont_require_annotations: Default::default(), disable_gdb_pretty_printers: false, compare_output_by_lines: false, @@ -653,6 +657,21 @@ impl TestProps { self.update_add_core_stubs(ln, config); + if let Some(flags) = config.parse_name_value_directive( + ln, + directives::CORE_STUBS_COMPILE_FLAGS, + testfile, + line_number, + ) { + let flags = split_flags(&flags); + for flag in &flags { + if flag == "--edition" || flag.starts_with("--edition=") { + panic!("you must use `//@ edition` to configure the edition"); + } + } + self.core_stubs_compile_flags.extend(flags); + } + if let Some(err_kind) = config.parse_name_value_directive( ln, DONT_REQUIRE_ANNOTATIONS, diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 0ef84fb4594..4fef8992567 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -19,6 +19,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-test-line-numbers-match", "compare-output-by-lines", "compile-flags", + "core-stubs-compile-flags", "disable-gdb-pretty-printers", "doc-flags", "dont-check-compiler-stderr", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 59bd3111ecf..bd32bec383f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1322,6 +1322,7 @@ impl<'test> TestCx<'test> { rustc.args(&["--crate-type", "rlib"]); rustc.arg("-Cpanic=abort"); + rustc.args(self.props.core_stubs_compile_flags.clone()); let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None); if !res.status.success() { @@ -1432,6 +1433,12 @@ impl<'test> TestCx<'test> { aux_rustc.arg("-L").arg(&aux_dir); + if aux_props.add_core_stubs { + let minicore_path = self.build_minicore(); + aux_rustc.arg("--extern"); + aux_rustc.arg(&format!("minicore={}", minicore_path)); + } + let auxres = aux_cx.compose_and_run( aux_rustc, aux_cx.config.compile_lib_path.as_path(), @@ -1858,14 +1865,13 @@ impl<'test> TestCx<'test> { } } - rustc.args(&self.props.compile_flags); - // FIXME(jieyouxu): we should report a fatal error or warning if user wrote `-Cpanic=` with - // something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`, - // however, by moving this last we should override previous `-Cpanic`s and - // `-Cforce-unwind-tables`s. Note that checking here is very fragile, because we'd have to - // account for all possible compile flag splittings (they have some... intricacies and are - // not yet normalized). + // something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`. + // + // We could apply these last and override any provided flags. That would ensure that the + // build works, but some tests want to exercise that mixing panic modes in specific ways is + // rejected. So we enable aborting panics and unwind tables before adding flags, just to + // change the default. // // `minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics. if self.props.add_core_stubs { @@ -1873,6 +1879,8 @@ impl<'test> TestCx<'test> { rustc.arg("-Cforce-unwind-tables=yes"); } + rustc.args(&self.props.compile_flags); + rustc } diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index e1a948c92fa..740118bb4a0 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -117,6 +117,41 @@ jobs: - name: rustdoc run: RUSTDOCFLAGS="-Dwarnings" ./miri doc --document-private-items + bootstrap: + name: bootstrap build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # Deliberately skipping `./.github/workflows/setup` as we do our own setup + - name: Add cache for cargo + id: cache + uses: actions/cache@v4 + with: + path: | + # Taken from <https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci>. + # Cache package/registry information + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + # Cache bootstrap downloads + ../rust/build/cache + key: cargo-bootstrap-${{ hashFiles('rust-version') }} + restore-keys: cargo-bootstrap + - name: prepare build environment + run: | + MIRIDIR=$(pwd) + cd .. + # Bootstrap needs at least depth 2 to function. + git clone https://github.com/rust-lang/rust/ rust --depth 2 --revision $(cat "$MIRIDIR/rust-version") + cd rust + # Replace the in-tree Miri with the current version. + rm src/tools/miri -rf + ln -s "$MIRIDIR" src/tools/miri + - name: check build + run: | + cd ../rust # ./x does not seem to like being invoked from elsewhere + ./x check miri + coverage: name: coverage report runs-on: ubuntu-latest @@ -130,7 +165,7 @@ jobs: # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! # And they should be added below in `cron-fail-notify` as well. conclusion: - needs: [test, style, coverage] + needs: [test, style, bootstrap, coverage] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run @@ -211,7 +246,7 @@ jobs: cron-fail-notify: name: cronjob failure notification runs-on: ubuntu-latest - needs: [test, style, coverage] + needs: [test, style, bootstrap, coverage] if: ${{ github.event_name == 'schedule' && failure() }} steps: # Send a Zulip notification diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index ee09b9b4b73..f1b52293123 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -130,15 +130,15 @@ impl Command { let new_commit = sh.read_file("rust-version")?.trim().to_owned(); let current_commit = { let rustc_info = cmd!(sh, "rustc +miri --version -v").read(); - if rustc_info.is_err() { - None - } else { - let metadata = rustc_version::version_meta_for(&rustc_info.unwrap())?; + if let Ok(rustc_info) = rustc_info { + let metadata = rustc_version::version_meta_for(&rustc_info)?; Some( metadata .commit_hash .ok_or_else(|| anyhow!("rustc metadata did not contain commit hash"))?, ) + } else { + None } }; // Check if we already are at that commit. diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0eb16a943d6..388e88fe43e 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3f1552a273e43e15f6ed240d00e1efdd6a53e65e +f6092f224d2b1774b31033f12d0bee626943b02f diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 7b4c533cfae..00f921b0f8a 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -244,8 +244,8 @@ pub(super) enum TransitionError { ChildAccessForbidden(Permission), /// A protector was triggered due to an invalid transition that loses /// too much permissions. - /// For example, if a protected tag goes from `Active` to `Disabled` due - /// to a foreign write this will produce a `ProtectedDisabled(Active)`. + /// For example, if a protected tag goes from `Unique` to `Disabled` due + /// to a foreign write this will produce a `ProtectedDisabled(Unique)`. /// This kind of error can only occur on foreign accesses. ProtectedDisabled(Permission), /// Cannot deallocate because some tag in the allocation is strongly protected. @@ -504,7 +504,7 @@ impl DisplayFmt { if let Some(perm) = perm { format!( "{ac}{st}", - ac = if perm.is_accessed() { self.accessed.yes } else { self.accessed.no }, + ac = if perm.accessed() { self.accessed.yes } else { self.accessed.no }, st = perm.permission().short_name(), ) } else { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs index 928b3e6baef..90df05d36d9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs @@ -24,7 +24,7 @@ use super::tree::AccessRelatedness; /// "manually" reset the parent's SIFA to be at least as strong as the new child's. This is accomplished with the `ensure_no_stronger_than` method. /// /// Note that we derive Ord and PartialOrd, so the order in which variants are listed below matters: -/// None < Read < Write. Do not change that order. See the `test_order` test. +/// None < Read < Write (weaker to stronger). Do not change that order. See the `test_order` test. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] pub enum IdempotentForeignAccess { #[default] diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index bed65440dc9..6e5b5c807aa 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -294,24 +294,6 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })); } - let span = this.machine.current_span(); - - // When adding a new node, the SIFA of its parents needs to be updated, potentially across - // the entire memory range. For the parts that are being accessed below, the access itself - // trivially takes care of that. However, we have to do some more work to also deal with the - // parts that are not being accessed. Specifically what we do is that we call - // `update_last_accessed_after_retag` on the SIFA of the permission set for the part of - // memory outside `perm_map` -- so that part is definitely taken care of. The remaining - // concern is the part of memory that is in the range of `perms_map`, but not accessed - // below. There we have two cases: - // * If the type is `!Freeze`, then the non-accessed part uses `nonfreeze_perm`, so the - // `nonfreeze_perm` initialized parts are also fine. We enforce the `freeze_perm` parts to - // be accessed via the assert below, and thus everything is taken care of. - // * If the type is `Freeze`, then `freeze_perm` is used everywhere (both inside and outside - // the initial range), and we update everything to have the `freeze_perm`'s SIFA, so there - // are no issues. (And this assert below is not actually needed in this case). - assert!(new_perm.freeze_access); - let protected = new_perm.protector.is_some(); let precise_interior_mut = this .machine @@ -337,7 +319,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { LocationState::new_non_accessed(perm, sifa) } }; - let perms_map = if !precise_interior_mut { + let inside_perms = if !precise_interior_mut { // For `!Freeze` types, just pretend the entire thing is an `UnsafeCell`. let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env()); let state = loc_state(ty_is_freeze); @@ -364,8 +346,8 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let alloc_extra = this.get_alloc_extra(alloc_id)?; let mut tree_borrows = alloc_extra.borrow_tracker_tb().borrow_mut(); - for (perm_range, perm) in perms_map.iter_all() { - if perm.is_accessed() { + for (perm_range, perm) in inside_perms.iter_all() { + if perm.accessed() { // Some reborrows incur a read access to the parent. // Adjust range to be relative to allocation start (rather than to `place`). let range_in_alloc = AllocRange { @@ -401,10 +383,10 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { base_offset, orig_tag, new_tag, - perms_map, + inside_perms, new_perm.outside_perm, protected, - span, + this.machine.current_span(), )?; drop(tree_borrows); diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 390435e58d1..e21775c9f23 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -14,7 +14,7 @@ enum PermissionPriv { Cell, /// represents: a local mutable reference that has not yet been written to; /// allows: child reads, foreign reads; - /// affected by: child writes (becomes Active), + /// affected by: child writes (becomes Unique), /// rejects: foreign writes (Disabled). /// /// `ReservedFrz` is mostly for types that are `Freeze` (no interior mutability). @@ -31,17 +31,17 @@ enum PermissionPriv { /// This is so that the behavior of `Reserved` adheres to the rules of `noalias`: /// - foreign-read then child-write is UB due to `conflicted`, /// - child-write then foreign-read is UB since child-write will activate and then - /// foreign-read disables a protected `Active`, which is UB. + /// foreign-read disables a protected `Unique`, which is UB. ReservedFrz { conflicted: bool }, /// Alternative version of `ReservedFrz` made for types with interior mutability. /// allows: child reads, foreign reads, foreign writes (extra); - /// affected by: child writes (becomes Active); + /// affected by: child writes (becomes Unique); /// rejects: nothing. ReservedIM, /// represents: a unique pointer; /// allows: child reads, child writes; /// rejects: foreign reads (Frozen), foreign writes (Disabled). - Active, + Unique, /// represents: a shared pointer; /// allows: all read accesses; /// rejects child writes (UB), foreign writes (Disabled). @@ -56,7 +56,7 @@ use super::foreign_access_skipping::IdempotentForeignAccess; impl PartialOrd for PermissionPriv { /// PermissionPriv is ordered by the reflexive transitive closure of - /// `Reserved(conflicted=false) < Reserved(conflicted=true) < Active < Frozen < Disabled`. + /// `Reserved(conflicted=false) < Reserved(conflicted=true) < Unique < Frozen < Disabled`. /// `Reserved` that have incompatible `ty_is_freeze` are incomparable to each other. /// This ordering matches the reachability by transitions, as asserted by the exhaustive test /// `permissionpriv_partialord_is_reachability`. @@ -76,8 +76,8 @@ impl PartialOrd for PermissionPriv { (_, Disabled) => Less, (Frozen, _) => Greater, (_, Frozen) => Less, - (Active, _) => Greater, - (_, Active) => Less, + (Unique, _) => Greater, + (_, Unique) => Less, (ReservedIM, ReservedIM) => Equal, (ReservedFrz { conflicted: c1 }, ReservedFrz { conflicted: c2 }) => { // `bool` is ordered such that `false <= true`, so this works as intended. @@ -115,8 +115,8 @@ impl PermissionPriv { // Famously, ReservedIM survives foreign writes. It is never protected. ReservedIM if prot => unreachable!("Protected ReservedIM should not exist!"), ReservedIM => IdempotentForeignAccess::Write, - // Active changes on any foreign access (becomes Frozen/Disabled). - Active => IdempotentForeignAccess::None, + // Unique changes on any foreign access (becomes Frozen/Disabled). + Unique => IdempotentForeignAccess::None, // Frozen survives foreign reads, but not writes. Frozen => IdempotentForeignAccess::Read, // Disabled survives foreign reads and writes. It survives them @@ -139,12 +139,12 @@ mod transition { Disabled => return None, // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read // accesses, since the data is not being mutated. Hence the `{ .. }`. - readable @ (Cell | ReservedFrz { .. } | ReservedIM | Active | Frozen) => readable, + readable @ (Cell | ReservedFrz { .. } | ReservedIM | Unique | Frozen) => readable, }) } /// A non-child node was read-accessed: keep `Reserved` but mark it as `conflicted` if it - /// is protected; invalidate `Active`. + /// is protected; invalidate `Unique`. fn foreign_read(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> { Some(match state { // Cell ignores foreign reads. @@ -167,10 +167,10 @@ mod transition { assert!(!protected); res } - Active => + Unique => if protected { // We wrote, someone else reads -- that's bad. - // (Since Active is always initialized, this move-to-protected will mean insta-UB.) + // (Since Unique is always initialized, this move-to-protected will mean insta-UB.) Disabled } else { // We don't want to disable here to allow read-read reordering: it is crucial @@ -180,7 +180,7 @@ mod transition { }) } - /// A child node was write-accessed: `Reserved` must become `Active` to obtain + /// A child node was write-accessed: `Reserved` must become `Unique` to obtain /// write permissions, `Frozen` and `Disabled` cannot obtain such permissions and produce UB. fn child_write(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> { Some(match state { @@ -192,7 +192,7 @@ mod transition { ReservedFrz { conflicted: true } if protected => return None, // A write always activates the 2-phase borrow, even with interior // mutability - ReservedFrz { .. } | ReservedIM | Active => Active, + ReservedFrz { .. } | ReservedIM | Unique => Unique, Frozen | Disabled => return None, }) } @@ -266,8 +266,8 @@ impl Permission { /// Default initial permission of the root of a new tree at inbounds positions. /// Must *only* be used for the root, this is not in general an "initial" permission! - pub fn new_active() -> Self { - Self { inner: Active } + pub fn new_unique() -> Self { + Self { inner: Unique } } /// Default initial permission of a reborrowed mutable reference that is either @@ -309,7 +309,7 @@ impl Permission { // Do not do perform access if it is a `Cell`, as this // can cause data races when using thread-safe data types. Cell => None, - Active => Some(AccessKind::Write), + Unique => Some(AccessKind::Write), _ => Some(AccessKind::Read), } } @@ -344,7 +344,7 @@ impl Permission { (_, Cell) => false, // ReservedIM can be replaced by anything besides Cell. // ReservedIM allows all transitions, but unlike Cell, a local write - // to ReservedIM transitions to Active, while it is a no-op for Cell. + // to ReservedIM transitions to Unique, while it is a no-op for Cell. (ReservedIM, _) => true, (_, ReservedIM) => false, // Reserved (as parent, where conflictedness does not matter) @@ -352,12 +352,12 @@ impl Permission { // since ReservedIM and Cell alone would survive foreign writes (ReservedFrz { .. }, _) => true, (_, ReservedFrz { .. }) => false, - // Active can not be replaced by something surviving + // Unique can not be replaced by something surviving // foreign reads and then remaining writable (i.e., Reserved*). // Replacing a state by itself is always okay, even if the child state is protected. - // Active can be replaced by Frozen, since it is not protected. - (Active, Active | Frozen | Disabled) => true, - (_, Active) => false, + // Unique can be replaced by Frozen, since it is not protected. + (Unique, Unique | Frozen | Disabled) => true, + (_, Unique) => false, // Frozen can only be replaced by Disabled (and itself). (Frozen, Frozen | Disabled) => true, (_, Frozen) => false, @@ -410,7 +410,7 @@ pub mod diagnostics { ReservedFrz { conflicted: false } => "Reserved", ReservedFrz { conflicted: true } => "Reserved (conflicted)", ReservedIM => "Reserved (interior mutable)", - Active => "Active", + Unique => "Unique", Frozen => "Frozen", Disabled => "Disabled", } @@ -441,7 +441,7 @@ pub mod diagnostics { ReservedFrz { conflicted: false } => "Res ", ReservedFrz { conflicted: true } => "ResC", ReservedIM => "ReIM", - Active => "Act ", + Unique => "Act ", Frozen => "Frz ", Disabled => "Dis ", } @@ -455,7 +455,7 @@ pub mod diagnostics { assert!(self.is_possible()); assert!(!self.is_noop()); match (self.from, self.to) { - (_, Active) => "the first write to a 2-phase borrowed mutable reference", + (_, Unique) => "the first write to a 2-phase borrowed mutable reference", (_, Frozen) => "a loss of write permissions", (ReservedFrz { conflicted: false }, ReservedFrz { conflicted: true }) => "a temporary loss of write permissions until function exit", @@ -472,8 +472,8 @@ pub mod diagnostics { /// /// Irrelevant events: /// - modifications of write permissions when the error is related to read permissions - /// (on failed reads and protected `Frozen -> Disabled`, ignore `Reserved -> Active`, - /// `Reserved(conflicted=false) -> Reserved(conflicted=true)`, and `Active -> Frozen`) + /// (on failed reads and protected `Frozen -> Disabled`, ignore `Reserved -> Unique`, + /// `Reserved(conflicted=false) -> Reserved(conflicted=true)`, and `Unique -> Frozen`) /// - all transitions for attempts to deallocate strongly protected tags /// /// # Panics @@ -481,10 +481,10 @@ pub mod diagnostics { /// This function assumes that its arguments apply to the same location /// and that they were obtained during a normal execution. It will panic otherwise. /// - all transitions involved in `self` and `err` should be increasing - /// (Reserved < Active < Frozen < Disabled); + /// (Reserved < Unique < Frozen < Disabled); /// - between `self` and `err` the permission should also be increasing, /// so all permissions inside `err` should be greater than `self.1`; - /// - `Active`, `Reserved(conflicted=false)`, and `Cell` cannot cause an error + /// - `Unique`, `Reserved(conflicted=false)`, and `Cell` cannot cause an error /// due to insufficient permissions, so `err` cannot be a `ChildAccessForbidden(_)` /// of either of them; /// - `err` should not be `ProtectedDisabled(Disabled)`, because the protected @@ -500,11 +500,11 @@ pub mod diagnostics { TransitionError::ChildAccessForbidden(insufficient) => { // Show where the permission was gained then lost, // but ignore unrelated permissions. - // This eliminates transitions like `Active -> Frozen` + // This eliminates transitions like `Unique -> Frozen` // when the error is a failed `Read`. match (self.to, insufficient.inner) { (Frozen, Frozen) => true, - (Active, Frozen) => true, + (Unique, Frozen) => true, (Disabled, Disabled) => true, ( ReservedFrz { conflicted: true, .. }, @@ -512,14 +512,14 @@ pub mod diagnostics { ) => true, // A pointer being `Disabled` is a strictly stronger source of // errors than it being `Frozen`. If we try to access a `Disabled`, - // then where it became `Frozen` (or `Active` or `Reserved`) is the least + // then where it became `Frozen` (or `Unique` or `Reserved`) is the least // of our concerns for now. - (ReservedFrz { conflicted: true } | Active | Frozen, Disabled) => false, + (ReservedFrz { conflicted: true } | Unique | Frozen, Disabled) => false, (ReservedFrz { conflicted: true }, Frozen) => false, - // `Active`, `Reserved`, and `Cell` have all permissions, so a - // `ChildAccessForbidden(Reserved | Active)` can never exist. - (_, Active) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => + // `Unique`, `Reserved`, and `Cell` have all permissions, so a + // `ChildAccessForbidden(Reserved | Unique)` can never exist. + (_, Unique) | (_, ReservedFrz { conflicted: false }) | (_, Cell) => unreachable!("this permission cannot cause an error"), // No transition has `Reserved { conflicted: false }` or `ReservedIM` // as its `.to` unless it's a noop. `Cell` cannot be in its `.to` @@ -527,11 +527,11 @@ pub mod diagnostics { (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => unreachable!("self is a noop transition"), // All transitions produced in normal executions (using `apply_access`) - // change permissions in the order `Reserved -> Active -> Frozen -> Disabled`. + // change permissions in the order `Reserved -> Unique -> Frozen -> Disabled`. // We assume that the error was triggered on the same location that // the transition `self` applies to, so permissions found must be increasing // in the order `self.from < self.to <= insufficient.inner` - (Active | Frozen | Disabled, ReservedFrz { .. } | ReservedIM) + (Unique | Frozen | Disabled, ReservedFrz { .. } | ReservedIM) | (Disabled, Frozen) | (ReservedFrz { .. }, ReservedIM) => unreachable!("permissions between self and err must be increasing"), @@ -540,29 +540,29 @@ pub mod diagnostics { TransitionError::ProtectedDisabled(before_disabled) => { // Show how we got to the starting point of the forbidden transition, // but ignore what came before. - // This eliminates transitions like `Reserved -> Active` + // This eliminates transitions like `Reserved -> Unique` // when the error is a `Frozen -> Disabled`. match (self.to, before_disabled.inner) { // We absolutely want to know where it was activated/frozen/marked // conflicted. - (Active, Active) => true, + (Unique, Unique) => true, (Frozen, Frozen) => true, ( ReservedFrz { conflicted: true, .. }, ReservedFrz { conflicted: true, .. }, ) => true, // If the error is a transition `Frozen -> Disabled`, then we don't really - // care whether before that was `Reserved -> Active -> Frozen` or + // care whether before that was `Reserved -> Unique -> Frozen` or // `Frozen` directly. // The error will only show either // - created as Reserved { conflicted: false }, // then Reserved { .. } -> Disabled is forbidden // - created as Reserved { conflicted: false }, - // then Active -> Disabled is forbidden + // then Unique -> Disabled is forbidden // A potential `Reserved { conflicted: false } // -> Reserved { conflicted: true }` is inexistant or irrelevant, - // and so is the `Reserved { conflicted: false } -> Active` - (Active, Frozen) => false, + // and so is the `Reserved { conflicted: false } -> Unique` + (Unique, Frozen) => false, (ReservedFrz { conflicted: true }, _) => false, (_, Disabled) => @@ -575,12 +575,12 @@ pub mod diagnostics { (ReservedFrz { conflicted: false } | ReservedIM | Cell, _) => unreachable!("self is a noop transition"), - // Permissions only evolve in the order `Reserved -> Active -> Frozen -> Disabled`, + // Permissions only evolve in the order `Reserved -> Unique -> Frozen -> Disabled`, // so permissions found must be increasing in the order // `self.from < self.to <= forbidden.from < forbidden.to`. - (Disabled, Cell | ReservedFrz { .. } | ReservedIM | Active | Frozen) - | (Frozen, Cell | ReservedFrz { .. } | ReservedIM | Active) - | (Active, Cell | ReservedFrz { .. } | ReservedIM) => + (Disabled, Cell | ReservedFrz { .. } | ReservedIM | Unique | Frozen) + | (Frozen, Cell | ReservedFrz { .. } | ReservedIM | Unique) + | (Unique, Cell | ReservedFrz { .. } | ReservedIM) => unreachable!("permissions between self and err must be increasing"), } } @@ -617,7 +617,7 @@ mod propagation_optimization_checks { impl Exhaustive for PermissionPriv { fn exhaustive() -> Box<dyn Iterator<Item = Self>> { Box::new( - vec![Active, Frozen, Disabled, ReservedIM, Cell] + vec![Unique, Frozen, Disabled, ReservedIM, Cell] .into_iter() .chain(<bool>::exhaustive().map(|conflicted| ReservedFrz { conflicted })), ) @@ -730,7 +730,7 @@ mod propagation_optimization_checks { #[test] // Check that all transitions are consistent with the order on PermissionPriv, - // i.e. Reserved -> Active -> Frozen -> Disabled + // i.e. Reserved -> Unique -> Frozen -> Disabled fn permissionpriv_partialord_is_reachability() { let reach = { let mut reach = rustc_data_structures::fx::FxHashSet::default(); diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 22bd63bd6b6..c4345c63289 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -11,7 +11,7 @@ //! - idempotency properties asserted in `perms.rs` (for optimizations) use std::ops::Range; -use std::{fmt, mem}; +use std::{cmp, fmt, mem}; use rustc_abi::Size; use rustc_data_structures::fx::FxHashSet; @@ -57,7 +57,7 @@ pub(super) struct LocationState { impl LocationState { /// Constructs a new initial state. It has neither been accessed, nor been subjected /// to any foreign access yet. - /// The permission is not allowed to be `Active`. + /// The permission is not allowed to be `Unique`. /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs` pub fn new_non_accessed(permission: Permission, sifa: IdempotentForeignAccess) -> Self { assert!(permission.is_initial() || permission.is_disabled()); @@ -73,23 +73,10 @@ impl LocationState { /// Check if the location has been accessed, i.e. if it has /// ever been accessed through a child pointer. - pub fn is_accessed(&self) -> bool { + pub fn accessed(&self) -> bool { self.accessed } - /// Check if the state can exist as the initial permission of a pointer. - /// - /// Do not confuse with `is_accessed`, the two are almost orthogonal - /// as apart from `Active` which is not initial and must be accessed, - /// any other permission can have an arbitrary combination of being - /// initial/accessed. - /// FIXME: when the corresponding `assert` in `tree_borrows/mod.rs` finally - /// passes and can be uncommented, remove this `#[allow(dead_code)]`. - #[cfg_attr(not(test), allow(dead_code))] - pub fn is_initial(&self) -> bool { - self.permission.is_initial() - } - pub fn permission(&self) -> Permission { self.permission } @@ -170,7 +157,7 @@ impl LocationState { } if self.permission.is_frozen() && access_kind == AccessKind::Read { // A foreign read to a `Frozen` tag will have almost no observable effect. - // It's a theorem that `Frozen` nodes have no active children, so all children + // It's a theorem that `Frozen` nodes have no `Unique` children, so all children // already survive foreign reads. Foreign reads in general have almost no // effect, the only further thing they could do is make protected `Reserved` // nodes become conflicted, i.e. make them reject child writes for the further @@ -265,7 +252,7 @@ pub(super) struct Node { pub children: SmallVec<[UniIndex; 4]>, /// Either `Reserved`, `Frozen`, or `Disabled`, it is the permission this tag will /// lazily be initialized to on the first access. - /// It is only ever `Disabled` for a tree root, since the root is initialized to `Active` by + /// It is only ever `Disabled` for a tree root, since the root is initialized to `Unique` by /// its own separate mechanism. default_initial_perm: Permission, /// The default initial (strongest) idempotent foreign access. @@ -598,14 +585,14 @@ impl Tree { }; let rperms = { let mut perms = UniValMap::default(); - // We manually set it to `Active` on all in-bounds positions. - // We also ensure that it is accessed, so that no `Active` but + // We manually set it to `Unique` on all in-bounds positions. + // We also ensure that it is accessed, so that no `Unique` but // not yet accessed nodes exist. Essentially, we pretend there - // was a write that initialized these to `Active`. + // was a write that initialized these to `Unique`. perms.insert( root_idx, LocationState::new_accessed( - Permission::new_active(), + Permission::new_unique(), IdempotentForeignAccess::None, ), ); @@ -618,30 +605,26 @@ impl Tree { impl<'tcx> Tree { /// Insert a new tag in the tree. /// - /// `initial_perms` defines the initial permissions for the part of memory - /// that is already considered "initialized" immediately. The ranges in this - /// map are relative to `base_offset`. - /// `default_perm` defines the initial permission for the rest of the allocation. - /// - /// For all non-accessed locations in the RangeMap (those that haven't had an - /// implicit read), their SIFA must be weaker than or as weak as the SIFA of - /// `default_perm`. + /// `inside_perm` defines the initial permissions for a block of memory starting at + /// `base_offset`. These may nor may not be already marked as "accessed". + /// `outside_perm` defines the initial permission for the rest of the allocation. + /// These are definitely not "accessed". pub(super) fn new_child( &mut self, base_offset: Size, parent_tag: BorTag, new_tag: BorTag, - initial_perms: DedupRangeMap<LocationState>, - default_perm: Permission, + inside_perms: DedupRangeMap<LocationState>, + outside_perm: Permission, protected: bool, span: Span, ) -> InterpResult<'tcx> { let idx = self.tag_mapping.insert(new_tag); let parent_idx = self.tag_mapping.get(&parent_tag).unwrap(); - assert!(default_perm.is_initial()); + assert!(outside_perm.is_initial()); let default_strongest_idempotent = - default_perm.strongest_idempotent_foreign_access(protected); + outside_perm.strongest_idempotent_foreign_access(protected); // Create the node self.nodes.insert( idx, @@ -649,47 +632,57 @@ impl<'tcx> Tree { tag: new_tag, parent: Some(parent_idx), children: SmallVec::default(), - default_initial_perm: default_perm, + default_initial_perm: outside_perm, default_initial_idempotent_foreign_access: default_strongest_idempotent, - debug_info: NodeDebugInfo::new(new_tag, default_perm, span), + debug_info: NodeDebugInfo::new(new_tag, outside_perm, span), }, ); // Register new_tag as a child of parent_tag self.nodes.get_mut(parent_idx).unwrap().children.push(idx); + // We need to know the weakest SIFA for `update_idempotent_foreign_access_after_retag`. + let mut min_sifa = default_strongest_idempotent; for (Range { start, end }, &perm) in - initial_perms.iter(Size::from_bytes(0), initial_perms.size()) + inside_perms.iter(Size::from_bytes(0), inside_perms.size()) { - assert!(perm.is_initial()); + assert!(perm.permission.is_initial()); + assert_eq!( + perm.idempotent_foreign_access, + perm.permission.strongest_idempotent_foreign_access(protected) + ); + + min_sifa = cmp::min(min_sifa, perm.idempotent_foreign_access); for (_perms_range, perms) in self .rperms .iter_mut(Size::from_bytes(start) + base_offset, Size::from_bytes(end - start)) { - assert!( - default_strongest_idempotent - >= perm.permission.strongest_idempotent_foreign_access(protected) - ); perms.insert(idx, perm); } } - // Inserting the new perms might have broken the SIFA invariant (see `foreign_access_skipping.rs`). - // We now weaken the recorded SIFA for our parents, until the invariant is restored. - // We could weaken them all to `LocalAccess`, but it is more efficient to compute the SIFA - // for the new permission statically, and use that. - // See the comment in `tb_reborrow` for why it is correct to use the SIFA of `default_uninit_perm`. - self.update_last_accessed_after_retag(parent_idx, default_strongest_idempotent); + // Inserting the new perms might have broken the SIFA invariant (see + // `foreign_access_skipping.rs`) if the SIFA we inserted is weaker than that of some parent. + // We now weaken the recorded SIFA for our parents, until the invariant is restored. We + // could weaken them all to `None`, but it is more efficient to compute the SIFA for the new + // permission statically, and use that. For this we need the *minimum* SIFA (`None` needs + // more fixup than `Write`). + self.update_idempotent_foreign_access_after_retag(parent_idx, min_sifa); interp_ok(()) } - /// Restores the SIFA "children are stronger" invariant after a retag. - /// See `foreign_access_skipping` and `new_child`. - fn update_last_accessed_after_retag( + /// Restores the SIFA "children are stronger"/"parents are weaker" invariant after a retag: + /// reduce the SIFA of `current` and its parents to be no stronger than `strongest_allowed`. + /// See `foreign_access_skipping.rs` and [`Tree::new_child`]. + fn update_idempotent_foreign_access_after_retag( &mut self, mut current: UniIndex, strongest_allowed: IdempotentForeignAccess, ) { + if strongest_allowed == IdempotentForeignAccess::Write { + // Nothing is stronger than `Write`. + return; + } // We walk the tree upwards, until the invariant is restored loop { let current_node = self.nodes.get_mut(current).unwrap(); @@ -755,9 +748,9 @@ impl<'tcx> Tree { == Some(&ProtectorKind::StrongProtector) // Don't check for protector if it is a Cell (see `unsafe_cell_deallocate` in `interior_mutability.rs`). // Related to https://github.com/rust-lang/rust/issues/55005. - && !perm.permission().is_cell() + && !perm.permission.is_cell() // Only trigger UB if the accessed bit is set, i.e. if the protector is actually protecting this offset. See #4579. - && perm.is_accessed() + && perm.accessed { Err(TransitionError::ProtectedDealloc) } else { @@ -790,7 +783,7 @@ impl<'tcx> Tree { /// - the access will be applied only to accessed locations of the allocation, /// - it will not be visible to children, /// - it will be recorded as a `FnExit` diagnostic access - /// - and it will be a read except if the location is `Active`, i.e. has been written to, + /// - and it will be a read except if the location is `Unique`, i.e. has been written to, /// in which case it will be a write. /// /// `LocationState::perform_access` will take care of raising transition diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index d9b3696e4f8..189e48eca72 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -106,7 +106,7 @@ fn tree_compacting_is_sound() { as_foreign_or_child(rel), kind, parent.permission(), - as_lazy_or_accessed(child.is_accessed()), + as_lazy_or_accessed(child.accessed()), child.permission(), as_protected(child_protected), np.permission(), @@ -122,7 +122,7 @@ fn tree_compacting_is_sound() { as_foreign_or_child(rel), kind, parent.permission(), - as_lazy_or_accessed(child.is_accessed()), + as_lazy_or_accessed(child.accessed()), child.permission(), as_protected(child_protected), nc.permission() @@ -375,7 +375,7 @@ mod spurious_read { impl LocStateProt { fn is_initial(&self) -> bool { - self.state.is_initial() + self.state.permission().is_initial() } fn perform_access(&self, kind: AccessKind, rel: AccessRelatedness) -> Result<Self, ()> { @@ -420,7 +420,7 @@ mod spurious_read { /// `(LocStateProt, LocStateProt)` where the two states are not guaranteed /// to be updated at the same time. /// Some `LocStateProtPair` may be unreachable through normal means - /// such as `x: Active, y: Active` in the case of mutually foreign pointers. + /// such as `x: Unique, y: Unique` in the case of mutually foreign pointers. struct LocStateProtPair { xy_rel: RelPosXY, x: LocStateProt, @@ -709,7 +709,7 @@ mod spurious_read { let mut err = 0; for pat in Pattern::exhaustive() { let Ok(initial_source) = pat.initial_state() else { - // Failed to retag `x` in the source (e.g. `y` was protected Active) + // Failed to retag `x` in the source (e.g. `y` was protected Unique) continue; }; // `x` must stay protected, but the function protecting `y` might return here diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 15d486c27e3..e4e7fb1d725 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -381,8 +381,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We need to drop our mutex borrow before unblock_thread // because it will be borrowed again in the unblock callback. drop(mutex); - if thread_id.is_some() { - this.unblock_thread(thread_id.unwrap(), BlockReason::Mutex)?; + if let Some(thread_id) = thread_id { + this.unblock_thread(thread_id, BlockReason::Mutex)?; } } Some(old_lock_count) diff --git a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr index 449a29088a0..dc8b4f6665a 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr @@ -16,7 +16,7 @@ LL | | Poll::<()>::Pending LL | | }) LL | | .await | |______________^ -help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [OFFSET] +help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [OFFSET] --> tests/fail/async-shared-mutable.rs:LL:CC | LL | *x = 1; diff --git a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr index 3c8ec7f7d3e..6a1f7761a41 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr @@ -7,7 +7,7 @@ LL | *y = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign read access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign read access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/both_borrows/box_noalias_violation.rs:LL:CC @@ -19,7 +19,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 { | ^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/both_borrows/box_noalias_violation.rs:LL:CC | LL | *x = 5; diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr index 6780e52c3ba..1547a6ca73a 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write6.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { *y = 2 }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign write access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign write access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/both_borrows/illegal_write6.rs:LL:CC @@ -19,7 +19,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | fn foo(a: &mut u32, y: *mut u32) -> u32 { | ^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/both_borrows/illegal_write6.rs:LL:CC | LL | *a = 1; diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr index 2266a9c39f9..2d9ce2aa1fb 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr @@ -7,7 +7,7 @@ LL | Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(a = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign read access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign read access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC @@ -19,7 +19,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | y.0 = 0; | ^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC | LL | y.0 = 0; diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr index b7f514de0af..42e391b5daf 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr @@ -7,7 +7,7 @@ LL | Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this reborrow (acting as a foreign read access) would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this reborrow (acting as a foreign read access) would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC @@ -19,7 +19,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | x | ^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC | LL | x diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 1995528e9f9..74706d6b9f6 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { ptr.write(S(0)) }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign write access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign write access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC @@ -24,7 +24,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | unsafe { ptr.write(S(0)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC | LL | unsafe { ptr.write(S(0)) }; diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index e506a61c6bb..c8c0e5c37ef 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { ptr.read() }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign read access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign read access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC @@ -24,7 +24,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | x.0 = 0; | ^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC | LL | x.0 = 0; diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr index b1aa2ba2886..b43e19c3905 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { ptr.read() }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign read access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign read access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC @@ -24,7 +24,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | unsafe { ptr.read() }; | ^^^^^^^^^^^^^^^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr index 0cf449ea3ec..deefb24b785 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { ptr.write(0) }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign write access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign write access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC @@ -24,7 +24,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC | LL | unsafe { ptr.write(0) }; diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr index a006c6feae4..76ccf39744d 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr @@ -7,7 +7,7 @@ LL | unsafe { ptr.write(0) }; = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child) - = help: this foreign write access would cause the protected tag <TAG> (currently Active) to become Disabled + = help: this foreign write access would cause the protected tag <TAG> (currently Unique) to become Disabled = help: protected tags must never be Disabled help: the accessed tag <TAG> was created here --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC @@ -24,7 +24,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved | LL | unsafe { ptr.write(0) }; | ^^^^^^^^^^^^^^^^^^^^^^^ -help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC | LL | unsafe { ptr.write(0) }; diff --git a/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr b/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr index 9e955a6d5b1..aff482abfa0 100644 --- a/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/alternate-read-write.stderr @@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Reserved | LL | let y = unsafe { &mut *(x as *mut u8) }; | ^^^^^^^^^^^^^^^^^^^^ -help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x1] +help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x1] --> tests/fail/tree_borrows/alternate-read-write.rs:LL:CC | LL | *y += 1; // Success diff --git a/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr index 7886029dccf..bfd6854514e 100644 --- a/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/fnentry_invalidation.stderr @@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Reserved | LL | let z = &mut x as *mut i32; | ^^^^^^ -help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/tree_borrows/fnentry_invalidation.rs:LL:CC | LL | *z = 1; diff --git a/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr index 2edbbd80569..7a713abcbc4 100644 --- a/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr @@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here, in the initial state Reserved | LL | let mref = &mut root; | ^^^^^^^^^ -help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x1] +help: the accessed tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x1] --> tests/fail/tree_borrows/parent_read_freezes_raw_mut.rs:LL:CC | LL | *ptr = 0; // Write diff --git a/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr index c00c67173b7..9a70d248aa0 100644 --- a/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/pass_invalid_mut.stderr @@ -18,7 +18,7 @@ help: the conflicting tag <TAG> was created here, in the initial state Reserved | LL | let xref = unsafe { &mut *xraw }; | ^^^^^^^^^^ -help: the conflicting tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4] +help: the conflicting tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4] --> tests/fail/tree_borrows/pass_invalid_mut.rs:LL:CC | LL | *xref = 18; // activate xref diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 024a14600b1..3e5d83911ee 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -60,8 +60,7 @@ fn main() { fn inner(x: &mut u8, b: IdxBarrier) { *x = 42; // activate immediately synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); - // A spurious write should be valid here because `x` is - // `Active` and protected. + // A spurious write should be valid here because `x` is `Unique` and protected. if cfg!(with) { synchronized!(b, "spurious write x (executed)"); *x = 64; diff --git a/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr index ba8ab472872..4b6308847bb 100644 --- a/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/return_invalid_mut.stderr @@ -18,7 +18,7 @@ help: the conflicting tag <TAG> was created here, in the initial state Reserved | LL | let ret = unsafe { &mut (*xraw).1 }; | ^^^^^^^^^^^^^^ -help: the conflicting tag <TAG> later transitioned to Active due to a child write access at offsets [0x4..0x8] +help: the conflicting tag <TAG> later transitioned to Unique due to a child write access at offsets [0x4..0x8] --> tests/fail/tree_borrows/return_invalid_mut.rs:LL:CC | LL | *ret = *ret; // activate diff --git a/src/tools/miri/tests/fail/tree_borrows/subtree_traversal_skipping_diagnostics.rs b/src/tools/miri/tests/fail/tree_borrows/subtree_traversal_skipping_diagnostics.rs index 6514334b09d..94a3bb80544 100644 --- a/src/tools/miri/tests/fail/tree_borrows/subtree_traversal_skipping_diagnostics.rs +++ b/src/tools/miri/tests/fail/tree_borrows/subtree_traversal_skipping_diagnostics.rs @@ -5,7 +5,7 @@ // When this method is called, the tree will be a single line and look like this, // with other_ptr being the root at the top -// other_ptr = root : Active +// other_ptr = root : Unique // intermediary : Frozen // an intermediary node // m : Reserved fn write_to_mut(m: &mut u8, other_ptr: *const u8) { diff --git a/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr b/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr deleted file mode 100644 index c7d72f70f40..00000000000 --- a/src/tools/miri/tests/fail/tree_borrows/unique.default.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: Undefined Behavior: write access through <TAG> at ALLOC[0x0] is forbidden - --> tests/fail/tree_borrows/unique.rs:LL:CC - | -LL | *uniq.as_ptr() = 3; - | ^^^^^^^^^^^^^^^^^^ 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> has state Frozen which forbids this child write access -help: the accessed tag <TAG> was created here, in the initial state Reserved - --> tests/fail/tree_borrows/unique.rs:LL:CC - | -LL | let refmut = &mut data; - | ^^^^^^^^^ -help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x1] - --> tests/fail/tree_borrows/unique.rs:LL:CC - | -LL | *uniq.as_ptr() = 1; // activation - | ^^^^^^^^^^^^^^^^^^ - = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference -help: the accessed tag <TAG> later transitioned to Frozen due to a foreign read access at offsets [0x0..0x1] - --> tests/fail/tree_borrows/unique.rs:LL:CC - | -LL | let _definitely_parent = data; // definitely Frozen by now - | ^^^^ - = help: this transition corresponds to a loss of write permissions - = note: BACKTRACE (of the first span): - = note: inside `main` at tests/fail/tree_borrows/unique.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/miri/tests/pass/0weak_memory/weak.rs b/src/tools/miri/tests/pass/0weak_memory/weak.rs index c752fc114ba..611733d0dac 100644 --- a/src/tools/miri/tests/pass/0weak_memory/weak.rs +++ b/src/tools/miri/tests/pass/0weak_memory/weak.rs @@ -13,6 +13,10 @@ use std::sync::atomic::Ordering::*; use std::sync::atomic::{AtomicUsize, fence}; use std::thread::spawn; +#[path = "../../utils/mod.rs"] +mod utils; +use utils::check_all_outcomes; + #[allow(dead_code)] #[derive(Copy, Clone)] struct EvilSend<T>(pub T); @@ -33,35 +37,6 @@ fn spin_until(loc: &AtomicUsize, val: usize) -> usize { val } -/// Check that the function produces the intended set of outcomes. -#[track_caller] -fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Debug>( - expected: impl IntoIterator<Item = T>, - generate: impl Fn() -> T, -) { - use std::collections::HashSet; - - let expected: HashSet<T> = HashSet::from_iter(expected); - let mut seen = HashSet::new(); - // Let's give it N times as many tries as we are expecting values. - let tries = expected.len() * 16; - for i in 0..tries { - let val = generate(); - assert!(expected.contains(&val), "got an unexpected value: {val:?}"); - seen.insert(val); - if i > tries / 2 && expected.len() == seen.len() { - // We saw everything and we did quite a few tries, let's avoid wasting time. - return; - } - } - // Let's see if we saw them all. - for val in expected { - if !seen.contains(&val) { - panic!("did not get value that should be possible: {val:?}"); - } - } -} - fn relaxed() { check_all_outcomes([0, 1, 2], || { let x = static_atomic(0); diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 3ce5ea8356b..67a14c2b389 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -8,12 +8,16 @@ #![allow(internal_features)] #![allow(unnecessary_transmutes)] +#[path = "../utils/mod.rs"] +mod utils; use std::any::type_name; use std::cmp::min; use std::fmt::{Debug, Display, LowerHex}; use std::hint::black_box; use std::{f32, f64}; +use utils::check_nondet; + /// Compare the two floats, allowing for $ulp many ULPs of error. /// /// ULP means "Units in the Last Place" or "Units of Least Precision". @@ -1415,12 +1419,12 @@ fn test_fmuladd() { #[inline(never)] pub fn test_operations_f32(a: f32, b: f32, c: f32) { - assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c); + assert_approx_eq!(fmuladdf32(a, b, c), a * b + c); } #[inline(never)] pub fn test_operations_f64(a: f64, b: f64, c: f64) { - assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c); + assert_approx_eq!(fmuladdf64(a, b, c), a * b + c); } test_operations_f32(0.1, 0.2, 0.3); @@ -1429,29 +1433,14 @@ fn test_fmuladd() { /// `min` and `max` on equal arguments are non-deterministic. fn test_min_max_nondet() { - /// Ensure that if we call the closure often enough, we see both `true` and `false.` - #[track_caller] - fn ensure_both(f: impl Fn() -> bool) { - let rounds = 32; - let first = f(); - for _ in 1..rounds { - if f() != first { - // We saw two different values! - return; - } - } - // We saw the same thing N times. - panic!("expected non-determinism, got {rounds} times the same result: {first:?}"); - } - - ensure_both(|| f16::min(0.0, -0.0).is_sign_positive()); - ensure_both(|| f16::max(0.0, -0.0).is_sign_positive()); - ensure_both(|| f32::min(0.0, -0.0).is_sign_positive()); - ensure_both(|| f32::max(0.0, -0.0).is_sign_positive()); - ensure_both(|| f64::min(0.0, -0.0).is_sign_positive()); - ensure_both(|| f64::max(0.0, -0.0).is_sign_positive()); - ensure_both(|| f128::min(0.0, -0.0).is_sign_positive()); - ensure_both(|| f128::max(0.0, -0.0).is_sign_positive()); + check_nondet(|| f16::min(0.0, -0.0).is_sign_positive()); + check_nondet(|| f16::max(0.0, -0.0).is_sign_positive()); + check_nondet(|| f32::min(0.0, -0.0).is_sign_positive()); + check_nondet(|| f32::max(0.0, -0.0).is_sign_positive()); + check_nondet(|| f64::min(0.0, -0.0).is_sign_positive()); + check_nondet(|| f64::max(0.0, -0.0).is_sign_positive()); + check_nondet(|| f128::min(0.0, -0.0).is_sign_positive()); + check_nondet(|| f128::max(0.0, -0.0).is_sign_positive()); } fn test_non_determinism() { @@ -1461,35 +1450,20 @@ fn test_non_determinism() { }; use std::{f32, f64}; - /// Ensure that the operation is non-deterministic - #[track_caller] - fn ensure_nondet<T: PartialEq + std::fmt::Debug>(f: impl Fn() -> T) { - let rounds = 16; - let first = f(); - for _ in 1..rounds { - if f() != first { - // We saw two different values! - return; - } - } - // We saw the same thing N times. - panic!("expected non-determinism, got {rounds} times the same result: {first:?}"); - } - macro_rules! test_operations_f { ($a:expr, $b:expr) => { - ensure_nondet(|| fadd_algebraic($a, $b)); - ensure_nondet(|| fsub_algebraic($a, $b)); - ensure_nondet(|| fmul_algebraic($a, $b)); - ensure_nondet(|| fdiv_algebraic($a, $b)); - ensure_nondet(|| frem_algebraic($a, $b)); + check_nondet(|| fadd_algebraic($a, $b)); + check_nondet(|| fsub_algebraic($a, $b)); + check_nondet(|| fmul_algebraic($a, $b)); + check_nondet(|| fdiv_algebraic($a, $b)); + check_nondet(|| frem_algebraic($a, $b)); unsafe { - ensure_nondet(|| fadd_fast($a, $b)); - ensure_nondet(|| fsub_fast($a, $b)); - ensure_nondet(|| fmul_fast($a, $b)); - ensure_nondet(|| fdiv_fast($a, $b)); - ensure_nondet(|| frem_fast($a, $b)); + check_nondet(|| fadd_fast($a, $b)); + check_nondet(|| fsub_fast($a, $b)); + check_nondet(|| fmul_fast($a, $b)); + check_nondet(|| fdiv_fast($a, $b)); + check_nondet(|| frem_fast($a, $b)); } }; } @@ -1499,70 +1473,70 @@ fn test_non_determinism() { } pub fn test_operations_f32(a: f32, b: f32) { test_operations_f!(a, b); - ensure_nondet(|| a.powf(b)); - ensure_nondet(|| a.powi(2)); - ensure_nondet(|| a.log(b)); - ensure_nondet(|| a.exp()); - ensure_nondet(|| 10f32.exp2()); - ensure_nondet(|| f32::consts::E.ln()); - ensure_nondet(|| 10f32.log10()); - ensure_nondet(|| 8f32.log2()); - ensure_nondet(|| 1f32.ln_1p()); - ensure_nondet(|| 27.0f32.cbrt()); - ensure_nondet(|| 3.0f32.hypot(4.0f32)); - ensure_nondet(|| 1f32.sin()); - ensure_nondet(|| 1f32.cos()); + check_nondet(|| a.powf(b)); + check_nondet(|| a.powi(2)); + check_nondet(|| a.log(b)); + check_nondet(|| a.exp()); + check_nondet(|| 10f32.exp2()); + check_nondet(|| f32::consts::E.ln()); + check_nondet(|| 10f32.log10()); + check_nondet(|| 8f32.log2()); + check_nondet(|| 1f32.ln_1p()); + check_nondet(|| 27.0f32.cbrt()); + check_nondet(|| 3.0f32.hypot(4.0f32)); + check_nondet(|| 1f32.sin()); + check_nondet(|| 1f32.cos()); // On i686-pc-windows-msvc , these functions are implemented by calling the `f64` version, // which means the little rounding errors Miri introduces are discarded by the cast down to // `f32`. Just skip the test for them. if !cfg!(all(target_os = "windows", target_env = "msvc", target_arch = "x86")) { - ensure_nondet(|| 1.0f32.tan()); - ensure_nondet(|| 1.0f32.asin()); - ensure_nondet(|| 5.0f32.acos()); - ensure_nondet(|| 1.0f32.atan()); - ensure_nondet(|| 1.0f32.atan2(2.0f32)); - ensure_nondet(|| 1.0f32.sinh()); - ensure_nondet(|| 1.0f32.cosh()); - ensure_nondet(|| 1.0f32.tanh()); + check_nondet(|| 1.0f32.tan()); + check_nondet(|| 1.0f32.asin()); + check_nondet(|| 5.0f32.acos()); + check_nondet(|| 1.0f32.atan()); + check_nondet(|| 1.0f32.atan2(2.0f32)); + check_nondet(|| 1.0f32.sinh()); + check_nondet(|| 1.0f32.cosh()); + check_nondet(|| 1.0f32.tanh()); } - ensure_nondet(|| 1.0f32.asinh()); - ensure_nondet(|| 2.0f32.acosh()); - ensure_nondet(|| 0.5f32.atanh()); - ensure_nondet(|| 5.0f32.gamma()); - ensure_nondet(|| 5.0f32.ln_gamma()); - ensure_nondet(|| 5.0f32.erf()); - ensure_nondet(|| 5.0f32.erfc()); + check_nondet(|| 1.0f32.asinh()); + check_nondet(|| 2.0f32.acosh()); + check_nondet(|| 0.5f32.atanh()); + check_nondet(|| 5.0f32.gamma()); + check_nondet(|| 5.0f32.ln_gamma()); + check_nondet(|| 5.0f32.erf()); + check_nondet(|| 5.0f32.erfc()); } pub fn test_operations_f64(a: f64, b: f64) { test_operations_f!(a, b); - ensure_nondet(|| a.powf(b)); - ensure_nondet(|| a.powi(2)); - ensure_nondet(|| a.log(b)); - ensure_nondet(|| a.exp()); - ensure_nondet(|| 50f64.exp2()); - ensure_nondet(|| 3f64.ln()); - ensure_nondet(|| f64::consts::E.log10()); - ensure_nondet(|| f64::consts::E.log2()); - ensure_nondet(|| 1f64.ln_1p()); - ensure_nondet(|| 27.0f64.cbrt()); - ensure_nondet(|| 3.0f64.hypot(4.0f64)); - ensure_nondet(|| 1f64.sin()); - ensure_nondet(|| 1f64.cos()); - ensure_nondet(|| 1.0f64.tan()); - ensure_nondet(|| 1.0f64.asin()); - ensure_nondet(|| 5.0f64.acos()); - ensure_nondet(|| 1.0f64.atan()); - ensure_nondet(|| 1.0f64.atan2(2.0f64)); - ensure_nondet(|| 1.0f64.sinh()); - ensure_nondet(|| 1.0f64.cosh()); - ensure_nondet(|| 1.0f64.tanh()); - ensure_nondet(|| 1.0f64.asinh()); - ensure_nondet(|| 3.0f64.acosh()); - ensure_nondet(|| 0.5f64.atanh()); - ensure_nondet(|| 5.0f64.gamma()); - ensure_nondet(|| 5.0f64.ln_gamma()); - ensure_nondet(|| 5.0f64.erf()); - ensure_nondet(|| 5.0f64.erfc()); + check_nondet(|| a.powf(b)); + check_nondet(|| a.powi(2)); + check_nondet(|| a.log(b)); + check_nondet(|| a.exp()); + check_nondet(|| 50f64.exp2()); + check_nondet(|| 3f64.ln()); + check_nondet(|| f64::consts::E.log10()); + check_nondet(|| f64::consts::E.log2()); + check_nondet(|| 1f64.ln_1p()); + check_nondet(|| 27.0f64.cbrt()); + check_nondet(|| 3.0f64.hypot(4.0f64)); + check_nondet(|| 1f64.sin()); + check_nondet(|| 1f64.cos()); + check_nondet(|| 1.0f64.tan()); + check_nondet(|| 1.0f64.asin()); + check_nondet(|| 5.0f64.acos()); + check_nondet(|| 1.0f64.atan()); + check_nondet(|| 1.0f64.atan2(2.0f64)); + check_nondet(|| 1.0f64.sinh()); + check_nondet(|| 1.0f64.cosh()); + check_nondet(|| 1.0f64.tanh()); + check_nondet(|| 1.0f64.asinh()); + check_nondet(|| 3.0f64.acosh()); + check_nondet(|| 0.5f64.atanh()); + check_nondet(|| 5.0f64.gamma()); + check_nondet(|| 5.0f64.ln_gamma()); + check_nondet(|| 5.0f64.erf()); + check_nondet(|| 5.0f64.erfc()); } pub fn test_operations_f128(a: f128, b: f128) { test_operations_f!(a, b); @@ -1574,15 +1548,15 @@ fn test_non_determinism() { test_operations_f128(25., 18.); // SNaN^0 = (1 | NaN) - ensure_nondet(|| f32::powf(SNAN_F32, 0.0).is_nan()); - ensure_nondet(|| f64::powf(SNAN_F64, 0.0).is_nan()); + check_nondet(|| f32::powf(SNAN_F32, 0.0).is_nan()); + check_nondet(|| f64::powf(SNAN_F64, 0.0).is_nan()); // 1^SNaN = (1 | NaN) - ensure_nondet(|| f32::powf(1.0, SNAN_F32).is_nan()); - ensure_nondet(|| f64::powf(1.0, SNAN_F64).is_nan()); + check_nondet(|| f32::powf(1.0, SNAN_F32).is_nan()); + check_nondet(|| f64::powf(1.0, SNAN_F64).is_nan()); // same as powf (keep it consistent): // x^SNaN = (1 | NaN) - ensure_nondet(|| f32::powi(SNAN_F32, 0).is_nan()); - ensure_nondet(|| f64::powi(SNAN_F64, 0).is_nan()); + check_nondet(|| f32::powi(SNAN_F32, 0).is_nan()); + check_nondet(|| f64::powi(SNAN_F64, 0).is_nan()); } diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 90281630740..c07ffdf9740 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -5,6 +5,10 @@ use std::fmt; use std::hint::black_box; +#[path = "../utils/mod.rs"] +mod utils; +use utils::check_all_outcomes; + fn ldexp(a: f64, b: i32) -> f64 { extern "C" { fn ldexp(x: f64, n: i32) -> f64; @@ -26,35 +30,6 @@ enum NaNKind { } use NaNKind::*; -/// Check that the function produces the intended set of outcomes. -#[track_caller] -fn check_all_outcomes<T: Eq + std::hash::Hash + fmt::Display>( - expected: impl IntoIterator<Item = T>, - generate: impl Fn() -> T, -) { - use std::collections::HashSet; - - let expected: HashSet<T> = HashSet::from_iter(expected); - let mut seen = HashSet::new(); - // Let's give it N times as many tries as we are expecting values. - let tries = expected.len() * 12; - for i in 0..tries { - let val = generate(); - assert!(expected.contains(&val), "got an unexpected value: {val}"); - seen.insert(val); - if i > tries / 2 && expected.len() == seen.len() { - // We saw everything and we did quite a few tries, let's avoid wasting time. - return; - } - } - // Let's see if we saw them all. - for val in expected { - if !seen.contains(&val) { - panic!("did not get value that should be possible: {val}"); - } - } -} - // -- f32 support #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash)] @@ -81,7 +56,7 @@ const F32_EXP: u32 = 8; // 8 bits of exponent const F32_MANTISSA: u32 = F32_SIGN_BIT - F32_EXP; const F32_NAN_PAYLOAD: u32 = F32_MANTISSA - 1; -impl fmt::Display for F32 { +impl fmt::Debug for F32 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Alaways show raw bits. write!(f, "0x{:08x} ", self.0)?; @@ -154,7 +129,7 @@ const F64_EXP: u32 = 11; // 11 bits of exponent const F64_MANTISSA: u32 = F64_SIGN_BIT - F64_EXP; const F64_NAN_PAYLOAD: u32 = F64_MANTISSA - 1; -impl fmt::Display for F64 { +impl fmt::Debug for F64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Alaways show raw bits. write!(f, "0x{:08x} ", self.0)?; diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs index b688405c4b1..abc156d49cb 100644 --- a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -3,73 +3,48 @@ use std::intrinsics::simd::simd_relaxed_fma; use std::intrinsics::{fmuladdf32, fmuladdf64}; use std::simd::prelude::*; -fn ensure_both_happen(f: impl Fn() -> bool) -> bool { - let mut saw_true = false; - let mut saw_false = false; - for _ in 0..50 { - let b = f(); - if b { - saw_true = true; - } else { - saw_false = true; - } - if saw_true && saw_false { - return true; - } - } - false -} +#[path = "../../utils/mod.rs"] +mod utils; +use utils::check_nondet; fn main() { - assert!( - ensure_both_happen(|| { - let a = std::hint::black_box(0.1_f64); - let b = std::hint::black_box(0.2); - let c = std::hint::black_box(-a * b); - // It is unspecified whether the following operation is fused or not. The - // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. - let x = unsafe { fmuladdf64(a, b, c) }; - x == 0.0 - }), - "`fmuladdf64` failed to be evaluated as both fused and unfused" - ); + check_nondet(|| { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = fmuladdf64(a, b, c); + x == 0.0 + }); - assert!( - ensure_both_happen(|| { - let a = std::hint::black_box(0.1_f32); - let b = std::hint::black_box(0.2); - let c = std::hint::black_box(-a * b); - // It is unspecified whether the following operation is fused or not. The - // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. - let x = unsafe { fmuladdf32(a, b, c) }; - x == 0.0 - }), - "`fmuladdf32` failed to be evaluated as both fused and unfused" - ); + check_nondet(|| { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = fmuladdf32(a, b, c); + x == 0.0 + }); - assert!( - ensure_both_happen(|| { - let a = f32x4::splat(std::hint::black_box(0.1)); - let b = f32x4::splat(std::hint::black_box(0.2)); - let c = std::hint::black_box(-a * b); - let x = unsafe { simd_relaxed_fma(a, b, c) }; - // Whether we fuse or not is a per-element decision, so sometimes these should be - // the same and sometimes not. - x[0] == x[1] - }), - "`simd_relaxed_fma` failed to be evaluated as both fused and unfused" - ); + check_nondet(|| { + let a = f32x4::splat(std::hint::black_box(0.1)); + let b = f32x4::splat(std::hint::black_box(0.2)); + let c = std::hint::black_box(-a * b); + let x = unsafe { simd_relaxed_fma(a, b, c) }; + // Whether we fuse or not is a per-element decision, so sometimes these should be + // the same and sometimes not. + x[0] == x[1] + }); - assert!( - ensure_both_happen(|| { - let a = f64x4::splat(std::hint::black_box(0.1)); - let b = f64x4::splat(std::hint::black_box(0.2)); - let c = std::hint::black_box(-a * b); - let x = unsafe { simd_relaxed_fma(a, b, c) }; - // Whether we fuse or not is a per-element decision, so sometimes these should be - // the same and sometimes not. - x[0] == x[1] - }), - "`simd_relaxed_fma` failed to be evaluated as both fused and unfused" - ); + check_nondet(|| { + let a = f64x4::splat(std::hint::black_box(0.1)); + let b = f64x4::splat(std::hint::black_box(0.2)); + let c = std::hint::black_box(-a * b); + let x = unsafe { simd_relaxed_fma(a, b, c) }; + // Whether we fuse or not is a per-element decision, so sometimes these should be + // the same and sometimes not. + x[0] == x[1] + }); } diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs index adf2f4e845b..4a868455c84 100644 --- a/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs +++ b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs @@ -20,7 +20,7 @@ pub fn main() { name!(ptr2); // We perform a write through `x`. - // Because `ptr1` is ReservedIM, a child write will make it transition to Active. + // Because `ptr1` is ReservedIM, a child write will make it transition to Unique. // Because `ptr2` is ReservedIM, a foreign write doesn't have any effect on it. let x = (*ptr1).get(); *x = 1; diff --git a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs index 4fbccef2367..edd649b91ed 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs +++ b/src/tools/miri/tests/pass/tree_borrows/reborrow-is-read.rs @@ -6,7 +6,7 @@ mod utils; // To check that a reborrow is counted as a Read access, we use a reborrow -// with no additional Read to Freeze an Active pointer. +// with no additional Read to Freeze an Unique pointer. fn main() { unsafe { @@ -15,7 +15,7 @@ fn main() { let alloc_id = alloc_id!(parent); let x = &mut *parent; name!(x); - *x = 0; // x is now Active + *x = 0; // x is now Unique print_state!(alloc_id); let y = &mut *parent; name!(y); diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.rs b/src/tools/miri/tests/pass/tree_borrows/reserved.rs index c57cd7fcf0a..83e1d9c70ed 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.rs +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.rs @@ -68,7 +68,7 @@ unsafe fn cell_unprotected_read() { } // Foreign Write on an interior mutable pointer is a noop. -// Also y must become Active. +// Also y must become Unique. unsafe fn cell_unprotected_write() { print("[interior mut] Foreign Write: Re* -> Re*"); let base = &mut UnsafeCell::new(0u64); @@ -97,7 +97,7 @@ unsafe fn int_protected_read() { } // Foreign Read on a Reserved is a noop. -// Also y must become Active. +// Also y must become Unique. unsafe fn int_unprotected_read() { print("[] Foreign Read: Res -> Res"); let base = &mut 0u8; diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs index 138ada4e20d..37f99962163 100644 --- a/src/tools/miri/tests/utils/mod.rs +++ b/src/tools/miri/tests/utils/mod.rs @@ -16,3 +16,53 @@ pub fn run_provenance_gc() { // SAFETY: No preconditions. The GC is fine to run at any time. unsafe { miri_run_provenance_gc() } } + +/// Check that the function produces the intended set of outcomes. +#[track_caller] +pub fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Debug>( + expected: impl IntoIterator<Item = T>, + generate: impl Fn() -> T, +) { + use std::collections::HashSet; + + let expected: HashSet<T> = HashSet::from_iter(expected); + let mut seen = HashSet::new(); + // Let's give it N times as many tries as we are expecting values. + let min_tries = std::cmp::max(20, expected.len() * 4); + let max_tries = expected.len() * 50; + for i in 0..max_tries { + let val = generate(); + assert!(expected.contains(&val), "got an unexpected value: {val:?}"); + seen.insert(val); + if i >= min_tries && expected.len() == seen.len() { + // We saw everything and we did enough tries, let's avoid wasting time. + return; + } + } + // Let's see if we saw them all. + if expected.len() == seen.len() { + return; + } + // Find the missing one. + for val in expected { + if !seen.contains(&val) { + panic!("did not get value that should be possible: {val:?}"); + } + } + unreachable!() +} + +/// Check that the operation is non-deterministic +#[track_caller] +pub fn check_nondet<T: PartialEq + std::fmt::Debug>(f: impl Fn() -> T) { + let rounds = 50; + let first = f(); + for _ in 1..rounds { + if f() != first { + // We saw two different values! + return; + } + } + // We saw the same thing N times. + panic!("expected non-determinism, got {rounds} times the same result: {first:?}"); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 301d4cca066..e5c213ca937 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -15,10 +15,6 @@ extern crate rustc_parse_format; #[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_parse_format as rustc_parse_format; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_abi; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; pub mod db; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 451622ef747..2e59a488e67 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -3,45 +3,24 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] -#[cfg(feature = "in-rust-tree")] -extern crate rustc_index; +// FIXME: We used to import `rustc_*` deps from `rustc_private` with `feature = "in-rust-tree" but +// temporarily switched to crates.io versions due to hardships that working on them from rustc +// demands corresponding changes on rust-analyzer at the same time. +// For details, see the zulip discussion below: +// https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/relying.20on.20in-tree.20.60rustc_type_ir.60.2F.60rustc_next_trait_solver.60/with/541055689 -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_index as rustc_index; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_abi; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_abi as rustc_abi; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_pattern_analysis; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_ast_ir; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_ast_ir as rustc_ast_ir; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_type_ir; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_type_ir as rustc_type_ir; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_next_trait_solver; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_data_structures as ena; - mod builder; mod chalk_db; mod chalk_ext; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs index 7ebefa76ed0..0b3582051bc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs @@ -36,8 +36,6 @@ impl<'db> Const<'db> { internee: kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - #[cfg(feature = "in-rust-tree")] - stable_hash: ena::fingerprint::Fingerprint::ZERO, }; Const::new_(interner.db(), InternedWrapperNoDebug(cached)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs index 86545415009..99b1354b633 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs @@ -227,8 +227,6 @@ impl<'db> Predicate<'db> { internee: kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - #[cfg(feature = "in-rust-tree")] - stable_hash: ena::fingerprint::Fingerprint::ZERO, }; Predicate::new_(interner.db(), InternedWrapperNoDebug(cached)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index c7a747ade3e..70139e86669 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -60,8 +60,6 @@ impl<'db> Ty<'db> { internee: kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - #[cfg(feature = "in-rust-tree")] - stable_hash: ena::fingerprint::Fingerprint::ZERO, }; Ty::new_(interner.db(), InternedWrapperNoDebug(cached)) } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index f8dacf0fb86..027a386abe8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -20,10 +20,6 @@ #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] -#[cfg(feature = "in-rust-tree")] -extern crate rustc_type_ir; - -#[cfg(not(feature = "in-rust-tree"))] extern crate ra_ap_rustc_type_ir as rustc_type_ir; mod attrs; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e275d3042cb..247080102fb 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -367,6 +367,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", + "find-msvc-tools", "flate2", "fluent-bundle", "fluent-langneg", diff --git a/src/tools/tidy/src/rustdoc_json.rs b/src/tools/tidy/src/rustdoc_json.rs index 7a53c08737f..ade774616c7 100644 --- a/src/tools/tidy/src/rustdoc_json.rs +++ b/src/tools/tidy/src/rustdoc_json.rs @@ -17,11 +17,13 @@ pub fn check(src_path: &Path, ci_info: &crate::CiInfo, diag_ctx: DiagCtx) { }; // First we check that `src/rustdoc-json-types` was modified. - if !crate::files_modified(ci_info, |p| p == RUSTDOC_JSON_TYPES) { + if !crate::files_modified(ci_info, |p| p.starts_with(RUSTDOC_JSON_TYPES)) { // `rustdoc-json-types` was not modified so nothing more to check here. - check.verbose_msg("`rustdoc-json-types` was not modified."); return; } + + check.message("`rustdoc-json-types` modified, checking format version"); + // Then we check that if `FORMAT_VERSION` was updated, the `Latest feature:` was also updated. match crate::git_diff(base_commit, src_path.join("rustdoc-json-types")) { Some(output) => { diff --git a/tests/assembly-llvm/aarch64-pointer-auth.rs b/tests/assembly-llvm/aarch64-pointer-auth.rs index 56a26df469f..e1ca6d77581 100644 --- a/tests/assembly-llvm/aarch64-pointer-auth.rs +++ b/tests/assembly-llvm/aarch64-pointer-auth.rs @@ -1,10 +1,13 @@ // Test that PAC instructions are emitted when branch-protection is specified. //@ add-core-stubs -//@ revisions: PACRET PAUTHLR_NOP PAUTHLR +//@ revisions: GCS PACRET PAUTHLR_NOP PAUTHLR //@ assembly-output: emit-asm //@ needs-llvm-components: aarch64 //@ compile-flags: --target aarch64-unknown-linux-gnu +//@ [GCS] min-llvm-version: 21 +//@ [GCS] ignore-apple (XCode version needs updating) +//@ [GCS] compile-flags: -Z branch-protection=gcs //@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf //@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf //@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf @@ -17,6 +20,7 @@ extern crate minicore; use minicore::*; +// GCS: .aeabi_attribute 2, 1 // Tag_Feature_GCS // PACRET: hint #25 // PACRET: hint #29 // PAUTHLR_NOP: hint #25 diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index b5c116cdfef..ebea9fe40f5 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -658,6 +658,9 @@ //@ revisions: x86_64_unknown_managarm_mlibc //@ [x86_64_unknown_managarm_mlibc] compile-flags: --target x86_64-unknown-managarm-mlibc //@ [x86_64_unknown_managarm_mlibc] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_motor +//@ [x86_64_unknown_motor] compile-flags: --target x86_64-unknown-motor +//@ [x86_64_unknown_motor] needs-llvm-components: x86 //@ revisions: x86_64_unknown_netbsd //@ [x86_64_unknown_netbsd] compile-flags: --target x86_64-unknown-netbsd //@ [x86_64_unknown_netbsd] needs-llvm-components: x86 diff --git a/tests/codegen-llvm/branch-protection.rs b/tests/codegen-llvm/branch-protection.rs index d67e494cc0d..f92259c941c 100644 --- a/tests/codegen-llvm/branch-protection.rs +++ b/tests/codegen-llvm/branch-protection.rs @@ -1,9 +1,10 @@ // Test that the correct module flags are emitted with different branch protection flags. //@ add-core-stubs -//@ revisions: BTI PACRET LEAF BKEY PAUTHLR PAUTHLR_BKEY PAUTHLR_LEAF PAUTHLR_BTI NONE +//@ revisions: BTI GCS PACRET LEAF BKEY PAUTHLR PAUTHLR_BKEY PAUTHLR_LEAF PAUTHLR_BTI NONE //@ needs-llvm-components: aarch64 //@ [BTI] compile-flags: -Z branch-protection=bti +//@ [GCS] compile-flags: -Z branch-protection=gcs //@ [PACRET] compile-flags: -Z branch-protection=pac-ret //@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf //@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key @@ -32,6 +33,9 @@ pub fn test() {} // BTI: !"sign-return-address-all", i32 0 // BTI: !"sign-return-address-with-bkey", i32 0 +// GCS: attributes [[ATTR]] = {{.*}} "guarded-control-stack" +// GCS: !"guarded-control-stack", i32 1 + // PACRET: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" // PACRET-SAME: "sign-return-address-key"="a_key" // PACRET: !"branch-target-enforcement", i32 0 diff --git a/tests/codegen-llvm/intrinsic-no-unnamed-attr.rs b/tests/codegen-llvm/intrinsic-no-unnamed-attr.rs index 4bec579831d..255f20e6ff6 100644 --- a/tests/codegen-llvm/intrinsic-no-unnamed-attr.rs +++ b/tests/codegen-llvm/intrinsic-no-unnamed-attr.rs @@ -7,7 +7,5 @@ use std::intrinsics::sqrtf32; // CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}} fn main() { - unsafe { - sqrtf32(0.0f32); - } + sqrtf32(0.0f32); } diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml b/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml new file mode 100644 index 00000000000..3c61c12a84e --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml @@ -0,0 +1,12 @@ +cargo-features = ["profile-rustflags"] + +[package] +name = "panic_scenarios" +version = "0.1.0" +edition = "2024" + +[lib] +path = "lib.rs" + +[profile.release] +rustflags = ["-Zmerge-functions=disabled", "-Zcodegen-source-order", "--emit=llvm-ir"] diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs b/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs new file mode 100644 index 00000000000..1e20da93ba8 --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs @@ -0,0 +1,65 @@ +#![no_std] + +#[unsafe(no_mangle)] +pub fn panic_noarg() { + // CHECK-LABEL: @panic_noarg( + // CHECK-NEXT: start: + // CHECK-NEXT: tail call void @llvm.trap() + panic!(); +} + +#[unsafe(no_mangle)] +pub fn panic_str() { + // CHECK-LABEL: @panic_str( + // CHECK-NEXT: start: + // CHECK-NEXT: tail call void @llvm.trap() + panic!("ouch"); +} + +#[unsafe(no_mangle)] +pub fn bounds_check(x: &[u8], idx: usize) -> &u8 { + // CHECK-LABEL: @bounds_check( + // CHECK-NEXT: start: + // CHECK-NEXT: icmp ult + // CHECK-NEXT: br i1 + // CHECK: bb1: + // CHECK-NEXT: getelementptr inbounds nuw i8 + // CHECK-NEXT: ret ptr + // CHECK: panic: + // CHECK-NEXT: tail call void @llvm.trap() + &x[idx] +} + +#[unsafe(no_mangle)] +pub fn str_bounds_check(x: &str, idx: usize) -> &str { + // CHECK-LABEL: @str_bounds_check( + // CHECK-NOT: call + // CHECK: tail call void @llvm.trap() + // CHECK-NOT: call + &x[idx..] +} + +#[unsafe(no_mangle)] +pub fn unsigned_integer_div(x: u16, y: u16) -> u16 { + // CHECK-LABEL: @unsigned_integer_div( + // CHECK-NEXT: start: + // CHECK-NEXT: icmp eq i16 + // CHECK-NEXT: br i1 + // CHECK: bb1: + // CHECK-NEXT: udiv i16 + // CHECK-NEXT: ret i16 + // CHECK: panic: + // CHECK-NEXT: tail call void @llvm.trap() + x / y +} + +#[unsafe(no_mangle)] +pub fn refcell_already_borrowed() { + // CHECK-LABEL: @refcell_already_borrowed( + // CHECK-NOT: call + // CHECK: tail call void @llvm.trap() + // CHECK-NOT: call + let r = core::cell::RefCell::new(0u8); + let _guard = r.borrow_mut(); + r.borrow_mut(); +} diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs b/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs new file mode 100644 index 00000000000..d7a7a8bfd8c --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs @@ -0,0 +1,46 @@ +// This is a codegen test which checks that when code is compiled with panic=immediate-abort, +// we get a `tail call void @llvm.trap()` in user code instead of a call into the standard +// library's panic formatting code (such as panic_fmt) or one of the numerous panic outlining shims +// (such as slice_index_fail). + +#![deny(warnings)] + +use run_make_support::{cargo, llvm_filecheck, path, rfs, target}; + +fn main() { + let target_dir = path("target"); + + cargo() + .args(&[ + "build", + "--release", + "--lib", + "--manifest-path", + "Cargo.toml", + "-Zbuild-std=core", + "--target", + &target(), + ]) + .env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort") + .env("CARGO_TARGET_DIR", &target_dir) + .env("RUSTC_BOOTSTRAP", "1") + // Visual Studio 2022 requires that the LIB env var be set so it can + // find the Windows SDK. + .env("LIB", std::env::var("LIB").unwrap_or_default()) + .run(); + + let out_dir = target_dir.join(target()).join("release").join("deps"); + let ir_file = rfs::read_dir(out_dir) + .find_map(|e| { + let path = e.unwrap().path(); + let file_name = path.file_name().unwrap().to_str().unwrap(); + if file_name.starts_with("panic_scenarios") && file_name.ends_with(".ll") { + Some(path) + } else { + None + } + }) + .unwrap(); + + llvm_filecheck().patterns("lib.rs").input_file(ir_file).run(); +} diff --git a/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml b/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml new file mode 100644 index 00000000000..1e278d557c0 --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2024" diff --git a/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs b/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs b/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs new file mode 100644 index 00000000000..3eeef38c962 --- /dev/null +++ b/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs @@ -0,0 +1,39 @@ +// This test ensures we are able to compile and link a simple binary with panic=immediate-abort. +// The test panic-immediate-abort-codegen checks that panic strategy produces the desired codegen, +// but is based on compiling a library crate (which is the norm for codegen tests because it is +// cleaner and more portable). So this test ensures that we didn't mix up a cfg or a compiler +// implementation detail in a way that makes panic=immediate-abort encounter errors at link time. + +// Ideally this test would be run for most targets, but unfortunately: +// This test is currently written using `fn main() {}` which requires std. +// And since the default linker is only a linker for the host, we can't handle cross-compilation. +// Both of these shortcomings could be addressed at the cost of making the test more complicated. +//@ needs-target-std +//@ ignore-cross-compile + +#![deny(warnings)] + +use run_make_support::{cargo, path, target}; + +fn main() { + let target_dir = path("target"); + + cargo() + .current_dir("hello") + .args(&[ + "build", + "--release", + "--manifest-path", + "Cargo.toml", + "-Zbuild-std", + "--target", + &target(), + ]) + .env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort") + .env("CARGO_TARGET_DIR", &target_dir) + .env("RUSTC_BOOTSTRAP", "1") + // Visual Studio 2022 requires that the LIB env var be set so it can + // find the Windows SDK. + .env("LIB", std::env::var("LIB").unwrap_or_default()) + .run(); +} diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/dep-2-reexport.rs index 07444511472..07444511472 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs +++ b/tests/run-make/crate-loading/dep-2-reexport.rs diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/dependency-1.rs index bfeabccf5c1..bfeabccf5c1 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-1.rs +++ b/tests/run-make/crate-loading/dependency-1.rs diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/dependency-2.rs index 682d1ff64b8..682d1ff64b8 100644 --- a/tests/run-make/crate-loading/multiple-dep-versions-2.rs +++ b/tests/run-make/crate-loading/dependency-2.rs diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 6ad456e3e3e..8f257786123 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -6,12 +6,9 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("multiple-dep-versions-1.rs").run(); - rustc().input("multiple-dep-versions-2.rs").extra_filename("2").metadata("2").run(); - rustc() - .input("multiple-dep-versions-3.rs") - .extern_("dependency", rust_lib_name("dependency2")) - .run(); + rustc().input("dependency-1.rs").run(); + rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run(); + rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run(); let out = rustc() .input("multiple-dep-versions.rs") diff --git a/tests/run-make/pointer-auth-link-with-c-lto-clang/rmake.rs b/tests/run-make/pointer-auth-link-with-c-lto-clang/rmake.rs index 0a2186b0953..2ac5fdee063 100644 --- a/tests/run-make/pointer-auth-link-with-c-lto-clang/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c-lto-clang/rmake.rs @@ -1,12 +1,14 @@ // `-Z branch protection` is an unstable compiler feature which adds pointer-authentication // code (PAC), a useful hashing measure for verifying that pointers have not been modified. // This test checks that compilation and execution is successful when this feature is activated, -// with some of its possible extra arguments (bti, pac-ret, leaf) when doing LTO. +// with some of its possible extra arguments (bti, gcs, pac-ret, leaf) when doing LTO. // See https://github.com/rust-lang/rust/pull/88354 //@ needs-force-clang-based-tests //@ only-aarch64 // Reason: branch protection is not supported on other architectures +//@ ignore-apple +// Reason: XCode needs updating to support gcs //@ ignore-cross-compile // Reason: the compiled binary is executed @@ -19,7 +21,7 @@ fn main() { clang() .arg("-v") .lto("thin") - .arg("-mbranch-protection=bti+pac-ret+b-key+leaf") + .arg("-mbranch-protection=bti+gcs+pac-ret+b-key+leaf") .arg("-c") .out_exe("test.o") .input("test.c") @@ -30,7 +32,7 @@ fn main() { .opt_level("2") .linker(&env_var("CLANG")) .link_arg("-fuse-ld=lld") - .arg("-Zbranch-protection=bti,pac-ret,leaf") + .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") .output("test.bin") .run(); diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index a4d7454e575..1ddcb79d64f 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -1,11 +1,13 @@ // `-Z branch protection` is an unstable compiler feature which adds pointer-authentication // code (PAC), a useful hashing measure for verifying that pointers have not been modified. // This test checks that compilation and execution is successful when this feature is activated, -// with some of its possible extra arguments (bti, pac-ret, pc, leaf, b-key). +// with some of its possible extra arguments (bti, gcs, pac-ret, pc, leaf, b-key). // See https://github.com/rust-lang/rust/pull/88354 //@ only-aarch64 // Reason: branch protection is not supported on other architectures +//@ ignore-apple +// Reason: XCode needs updating to support gcs //@ ignore-cross-compile // Reason: the compiled binary is executed @@ -13,17 +15,17 @@ use run_make_support::{build_native_static_lib, cc, is_windows_msvc, llvm_ar, ru fn main() { build_native_static_lib("test"); - rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run(); + rustc().arg("-Zbranch-protection=bti,gcs,pac-ret,leaf").input("test.rs").run(); run("test"); cc().arg("-v") .arg("-c") .out_exe("test") .input("test.c") - .arg("-mbranch-protection=bti+pac-ret+leaf") + .arg("-mbranch-protection=bti+gcs+pac-ret+leaf") .run(); let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); - rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run(); + rustc().arg("-Zbranch-protection=bti,gcs,pac-ret,leaf").input("test.rs").run(); run("test"); // FIXME: +pc was only recently added to LLVM diff --git a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs new file mode 100644 index 00000000000..0b1e1948d5f --- /dev/null +++ b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs @@ -0,0 +1,28 @@ +// Running --merge=finalize without an input crate root should not trigger ICE. +// Issue: https://github.com/rust-lang/rust/issues/146646 + +//@ needs-target-std + +use run_make_support::{path, rustdoc}; + +fn main() { + let out_dir = path("out"); + let merged_dir = path("merged"); + let parts_out_dir = path("parts"); + rustdoc() + .input("sierra.rs") + .out_dir(&out_dir) + .arg("-Zunstable-options") + .arg(format!("--parts-out-dir={}", parts_out_dir.display())) + .arg("--merge=none") + .run(); + assert!(parts_out_dir.join("crate-info").exists()); + + let output = rustdoc() + .arg("-Zunstable-options") + .out_dir(&out_dir) + .arg(format!("--include-parts-dir={}", parts_out_dir.display())) + .arg("--merge=finalize") + .run(); + output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); +} diff --git a/tests/run-make/rustdoc-merge-no-input-finalize/sierra.rs b/tests/run-make/rustdoc-merge-no-input-finalize/sierra.rs new file mode 100644 index 00000000000..f8fc48341ed --- /dev/null +++ b/tests/run-make/rustdoc-merge-no-input-finalize/sierra.rs @@ -0,0 +1 @@ +pub struct Sierra; diff --git a/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs new file mode 100644 index 00000000000..d7efc201e7e --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.rs @@ -0,0 +1,25 @@ +// this test ensures that bad HTML with multiline tags doesn't cause an ICE +// regression test for https://github.com/rust-lang/rust/issues/146890 +#[deny(rustdoc::invalid_html_tags)] + +/// <TABLE +/// BORDER> +/// <TR +/// > +/// <TH +//~^ ERROR: unclosed HTML tag `TH` +/// >key +/// </TD +//~^ ERROR: unopened HTML tag `TD` +/// > +/// <TH +//~^ ERROR: unclosed HTML tag `TH` +/// >value +/// </TD +//~^ ERROR: unopened HTML tag `TD` +/// > +/// </TR +/// > +/// </TABLE +/// > +pub fn foo() {} diff --git a/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.stderr b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.stderr new file mode 100644 index 00000000000..64a82b3a952 --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-html-tags-ice-146890.stderr @@ -0,0 +1,38 @@ +error: unopened HTML tag `TD` + --> $DIR/invalid-html-tags-ice-146890.rs:12:5 + | +LL | /// </TD + | _____^ +LL | | +LL | | /// > + | |_____^ + | +note: the lint level is defined here + --> $DIR/invalid-html-tags-ice-146890.rs:3:8 + | +LL | #[deny(rustdoc::invalid_html_tags)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unopened HTML tag `TD` + --> $DIR/invalid-html-tags-ice-146890.rs:18:5 + | +LL | /// </TD + | _____^ +LL | | +LL | | /// > + | |_____^ + +error: unclosed HTML tag `TH` + --> $DIR/invalid-html-tags-ice-146890.rs:9:5 + | +LL | /// <TH + | ^^^ + +error: unclosed HTML tag `TH` + --> $DIR/invalid-html-tags-ice-146890.rs:15:5 + | +LL | /// <TH + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/rustdoc/reexport/private-mod-override-reexport.rs b/tests/rustdoc/reexport/private-mod-override-reexport.rs new file mode 100644 index 00000000000..849acc5fdae --- /dev/null +++ b/tests/rustdoc/reexport/private-mod-override-reexport.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/60926 +#![crate_name = "foo"] + +mod m1 { + pub mod m2 { + pub struct Foo; + } +} + +pub use m1::*; +use crate::m1::m2; + +//@ count foo/index.html '//a[@class="mod"]' 0 diff --git a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs new file mode 100644 index 00000000000..e5c1f47b9e0 --- /dev/null +++ b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Zdeduplicate-diagnostics=yes + +// Regression test for #146467. +#![feature(inherent_associated_types)] +//~^ WARN the feature `inherent_associated_types` is incomplete + +struct Foo<T>(T); + +impl<'a> Foo<fn(&())> { + //~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait + type Assoc = &'a (); +} + +fn foo(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} +//~^ ERROR mismatched types +//~| ERROR higher-ranked subtype error +fn main() {} diff --git a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr new file mode 100644 index 00000000000..4c0726d4ddc --- /dev/null +++ b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr @@ -0,0 +1,34 @@ +warning: the feature `inherent_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/hr-do-not-blame-outlives-static-ice.rs:4:12 + | +LL | #![feature(inherent_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/hr-do-not-blame-outlives-static-ice.rs:9:6 + | +LL | impl<'a> Foo<fn(&())> { + | ^^ unconstrained lifetime parameter + +error[E0308]: mismatched types + --> $DIR/hr-do-not-blame-outlives-static-ice.rs:14:11 + | +LL | fn foo(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo<for<'a> fn(&'a ())>` + found struct `Foo<for<'a> fn(&'a ())>` + +error: higher-ranked subtype error + --> $DIR/hr-do-not-blame-outlives-static-ice.rs:14:1 + | +LL | fn foo(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0308. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index 6b2e628e12e..39fee52a909 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, and `tvos` and 11 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, and `trusty` and 12 more = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr index 989a01f2244..4b5fc91c7eb 100644 --- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr @@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE` LL | cfg_macro::my_lib_macro_value!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `panic` are: `abort` and `unwind` + = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind` = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro` diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr index 95d10e014f3..0d99d061d28 100644 --- a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr @@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE` LL | cfg_macro::my_lib_macro_value!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `panic` are: `abort` and `unwind` + = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind` = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 6490fc63fd7..e62f741b302 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -80,7 +80,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `panic` are: `abort` and `unwind` + = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 28 warnings emitted diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg index 1cedbf75e4b..7ffbc64b074 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg @@ -1,7 +1,7 @@ -<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg"> +<svg width="740px" height="758px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-012 { fill: #5555FF } .container { diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg index 36a33b74042..5f1fcdb3d50 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg @@ -1,7 +1,7 @@ -<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg"> +<svg width="740px" height="758px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-012 { fill: #5555FF } .container { diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.svg b/tests/ui/diagnostic-flags/colored-session-opt-error.svg index 69f452f29f3..136c6fa5628 100644 --- a/tests/ui/diagnostic-flags/colored-session-opt-error.svg +++ b/tests/ui/diagnostic-flags/colored-session-opt-error.svg @@ -1,7 +1,7 @@ -<svg width="750px" height="74px" xmlns="http://www.w3.org/2000/svg"> +<svg width="740px" height="74px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-yellow { fill: #AA5500 } .container { padding: 0 10px; diff --git a/tests/ui/diagnostic-flags/terminal_urls.rs b/tests/ui/diagnostic-flags/terminal_urls.rs index 3c74e992395..631512ab579 100644 --- a/tests/ui/diagnostic-flags/terminal_urls.rs +++ b/tests/ui/diagnostic-flags/terminal_urls.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zterminal-urls=yes +//@ compile-flags: -Zterminal-urls=yes --error-format=human --color=always fn main() { - let () = 4; //~ ERROR + let () = 4; } diff --git a/tests/ui/diagnostic-flags/terminal_urls.stderr b/tests/ui/diagnostic-flags/terminal_urls.stderr deleted file mode 100644 index e5dfcdf6431..00000000000 --- a/tests/ui/diagnostic-flags/terminal_urls.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[]8;;https://doc.rust-lang.org/error_codes/E0308.htmlE0308]8;;]: mismatched types - --> $DIR/terminal_urls.rs:3:9 - | -LL | let () = 4; - | ^^ - this expression has type `{integer}` - | | - | expected integer, found `()` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-flags/terminal_urls.svg b/tests/ui/diagnostic-flags/terminal_urls.svg new file mode 100644 index 00000000000..fcb65637c4a --- /dev/null +++ b/tests/ui/diagnostic-flags/terminal_urls.svg @@ -0,0 +1,48 @@ +<svg width="740px" height="236px" xmlns="http://www.w3.org/2000/svg"> + <style> + .fg { fill: #AAAAAA } + .bg { fill: #000000 } + .fg-ansi256-009 { fill: #FF5555 } + .fg-ansi256-012 { fill: #5555FF } + .container { + padding: 0 10px; + line-height: 18px; + } + .bold { font-weight: bold; } + tspan { + font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace; + white-space: pre; + line-height: 18px; + } + </style> + + <rect width="100%" height="100%" y="0" rx="4.5" class="bg" /> + + <text xml:space="preserve" class="container fg"> + <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[</tspan><tspan class="fg-ansi256-009 bold"><a href="https://doc.rust-lang.org/error_codes/E0308.html">E0308</a></tspan><tspan class="fg-ansi256-009 bold">]</tspan><tspan class="bold">: mismatched types</tspan> +</tspan> + <tspan x="10px" y="46px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/terminal_urls.rs:3:9</tspan> +</tspan> + <tspan x="10px" y="64px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan> +</tspan> + <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> let () = 4;</tspan> +</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this expression has type `{integer}`</tspan> +</tspan> + <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> +</tspan> + <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `()`</tspan> +</tspan> + <tspan x="10px" y="154px"> +</tspan> + <tspan x="10px" y="172px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan> +</tspan> + <tspan x="10px" y="190px"> +</tspan> + <tspan x="10px" y="208px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan> +</tspan> + <tspan x="10px" y="226px"> +</tspan> + </text> + +</svg> diff --git a/tests/ui/diagnostic-flags/terminal_urls.windows.svg b/tests/ui/diagnostic-flags/terminal_urls.windows.svg new file mode 100644 index 00000000000..e7b46638399 --- /dev/null +++ b/tests/ui/diagnostic-flags/terminal_urls.windows.svg @@ -0,0 +1,49 @@ +<svg width="740px" height="236px" xmlns="http://www.w3.org/2000/svg"> + <style> + .fg { fill: #AAAAAA } + .bg { fill: #000000 } + .fg-ansi256-009 { fill: #FF5555 } + .fg-ansi256-014 { fill: #55FFFF } + .fg-ansi256-015 { fill: #FFFFFF } + .container { + padding: 0 10px; + line-height: 18px; + } + .bold { font-weight: bold; } + tspan { + font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace; + white-space: pre; + line-height: 18px; + } + </style> + + <rect width="100%" height="100%" y="0" rx="4.5" class="bg" /> + + <text xml:space="preserve" class="container fg"> + <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[</tspan><tspan class="fg-ansi256-009 bold"><a href="https://doc.rust-lang.org/error_codes/E0308.html">E0308</a></tspan><tspan class="fg-ansi256-009 bold">]</tspan><tspan class="fg-ansi256-015 bold">: mismatched types</tspan> +</tspan> + <tspan x="10px" y="46px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">--> </tspan><tspan>$DIR/terminal_urls.rs:3:9</tspan> +</tspan> + <tspan x="10px" y="64px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan> +</tspan> + <tspan x="10px" y="82px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> let () = 4;</tspan> +</tspan> + <tspan x="10px" y="100px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">-</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">this expression has type `{integer}`</tspan> +</tspan> + <tspan x="10px" y="118px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan> +</tspan> + <tspan x="10px" y="136px"><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `()`</tspan> +</tspan> + <tspan x="10px" y="154px"> +</tspan> + <tspan x="10px" y="172px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="fg-ansi256-015 bold">: aborting due to 1 previous error</tspan> +</tspan> + <tspan x="10px" y="190px"> +</tspan> + <tspan x="10px" y="208px"><tspan class="fg-ansi256-015 bold">For more information about this error, try `rustc --explain E0308`.</tspan> +</tspan> + <tspan x="10px" y="226px"> +</tspan> + </text> + +</svg> diff --git a/tests/ui/error-emitter/E0308-clarification.svg b/tests/ui/error-emitter/E0308-clarification.svg index 9432e3a4ee9..03ee973882d 100644 --- a/tests/ui/error-emitter/E0308-clarification.svg +++ b/tests/ui/error-emitter/E0308-clarification.svg @@ -1,7 +1,7 @@ <svg width="740px" height="668px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-012 { fill: #5555FF } .fg-magenta { fill: #AA00AA } diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg index 19818ab6146..d414f042f0a 100644 --- a/tests/ui/error-emitter/highlighting.svg +++ b/tests/ui/error-emitter/highlighting.svg @@ -1,7 +1,7 @@ <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg index f891bc1d2a6..92f9055cd1d 100644 --- a/tests/ui/error-emitter/highlighting.windows.svg +++ b/tests/ui/error-emitter/highlighting.windows.svg @@ -1,7 +1,7 @@ <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-014 { fill: #55FFFF } diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.svg index dd84234236d..5ffdc5a53fa 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.svg @@ -1,7 +1,7 @@ <svg width="1306px" height="866px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg index 144e57165da..37dc37e3e04 100644 --- a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg +++ b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg @@ -1,7 +1,7 @@ <svg width="1306px" height="866px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-014 { fill: #55FFFF } diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg index 7a88ac55b23..a774d558b58 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.svg +++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg @@ -1,7 +1,7 @@ -<svg width="2238px" height="3890px" xmlns="http://www.w3.org/2000/svg"> +<svg width="2288px" height="3890px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/error-emitter/unicode-output.svg b/tests/ui/error-emitter/unicode-output.svg index b253fff643b..bda4d1a2f28 100644 --- a/tests/ui/error-emitter/unicode-output.svg +++ b/tests/ui/error-emitter/unicode-output.svg @@ -1,7 +1,7 @@ <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/frontmatter/unclosed-6.rs b/tests/ui/frontmatter/unclosed-6.rs new file mode 100644 index 00000000000..ea8d4702f63 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-6.rs @@ -0,0 +1,12 @@ +--- +//~^ ERROR unclosed frontmatter +🦀--- + --- + +// This test checks the location of the --- recovered by the parser is not +// incorrectly tracked during the less fortunate recovery case and multiple +// candidates are found, as seen with #146847 + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/unclosed-6.stderr b/tests/ui/frontmatter/unclosed-6.stderr new file mode 100644 index 00000000000..01a13e87268 --- /dev/null +++ b/tests/ui/frontmatter/unclosed-6.stderr @@ -0,0 +1,19 @@ +error: unclosed frontmatter + --> $DIR/unclosed-6.rs:1:1 + | +LL | / --- +LL | | +LL | | 🦀--- +LL | | --- +... | +LL | | + | |_^ + | +note: frontmatter opening here was not closed + --> $DIR/unclosed-6.rs:1:1 + | +LL | --- + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.rs b/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.rs new file mode 100644 index 00000000000..dfdb816652c --- /dev/null +++ b/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Zdeduplicate-diagnostics=yes + +// Regression test for #146467. +trait Trait { type Assoc; } + +impl Trait for fn(&()) { type Assoc = (); } + +fn f(_: for<'a> fn(<fn(&'a ()) as Trait>::Assoc)) {} +//~^ ERROR implementation of `Trait` is not general enough +//~| ERROR higher-ranked subtype error + +fn main() {} diff --git a/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.stderr b/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.stderr new file mode 100644 index 00000000000..c75a063e45f --- /dev/null +++ b/tests/ui/higher-ranked/do-not-blame-outlives-static-ice.stderr @@ -0,0 +1,17 @@ +error: implementation of `Trait` is not general enough + --> $DIR/do-not-blame-outlives-static-ice.rs:8:9 + | +LL | fn f(_: for<'a> fn(<fn(&'a ()) as Trait>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `for<'a> fn(&'a ())` must implement `Trait`, for any lifetime `'0`... + = note: ...but `Trait` is actually implemented for the type `for<'a> fn(&'a ())` + +error: higher-ranked subtype error + --> $DIR/do-not-blame-outlives-static-ice.rs:8:1 + | +LL | fn f(_: for<'a> fn(<fn(&'a ()) as Trait>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg index 73acb072ac5..6077dbdc200 100644 --- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg +++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg @@ -1,7 +1,7 @@ -<svg width="1188px" height="398px" xmlns="http://www.w3.org/2000/svg"> +<svg width="1096px" height="398px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/intrinsics/intrinsic-fmuladd.rs b/tests/ui/intrinsics/intrinsic-fmuladd.rs index d03297884f7..ab4285590cb 100644 --- a/tests/ui/intrinsics/intrinsic-fmuladd.rs +++ b/tests/ui/intrinsics/intrinsic-fmuladd.rs @@ -11,7 +11,7 @@ macro_rules! assert_approx_eq { } fn main() { - unsafe { + { let nan: f32 = f32::NAN; let inf: f32 = f32::INFINITY; let neg_inf: f32 = f32::NEG_INFINITY; @@ -25,7 +25,7 @@ fn main() { assert_eq!(fmuladdf32(8.9, inf, 3.2), inf); assert_eq!(fmuladdf32(-3.2, 2.4, neg_inf), neg_inf); } - unsafe { + { let nan: f64 = f64::NAN; let inf: f64 = f64::INFINITY; let neg_inf: f64 = f64::NEG_INFINITY; diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index aea6f838e0d..1307a85c8b6 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -22,7 +22,7 @@ LL | std::intrinsics::floorf32, | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | = note: expected fn pointer `unsafe fn(_) -> _` - found fn item `unsafe fn(_) -> _ {floorf32}` + found fn item `fn(_) -> _ {floorf32}` error: aborting due to 3 previous errors diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr index dae08119dbc..277111a41f2 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr @@ -1,2 +1,2 @@ -error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected +error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set) was expected diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr index 13f79e94674..e1ade01d2fe 100644 --- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr @@ -1,2 +1,2 @@ -error: incorrect value `pc` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected +error: incorrect value `pc` for unstable option `branch-protection` - a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set) was expected diff --git a/tests/ui/iterators/issue-58952-filter-type-length.rs b/tests/ui/iterators/issue-58952-filter-type-length.rs index 6730865b6c7..525a2e39a91 100644 --- a/tests/ui/iterators/issue-58952-filter-type-length.rs +++ b/tests/ui/iterators/issue-58952-filter-type-length.rs @@ -2,7 +2,7 @@ //! This snippet causes the type length to blowup exponentially, //! so check that we don't accidentally exceed the type length limit. -// FIXME: Once the size of iterator adaptors is further reduced, +// FIXME: Once the size of iterator adapters is further reduced, // increase the complexity of this test. use std::collections::VecDeque; diff --git a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs index bb537f855a4..7de786dff3b 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs @@ -1,4 +1,4 @@ -//@ edition:2024 +//@ reference: destructors.scope.lifetime-extension.exprs fn temp() -> String { String::from("Hello") @@ -22,7 +22,7 @@ fn main() { let a = &temp(); let b = Some(&temp()); let c = Option::Some::<&String>(&temp()); - use Option::Some as S; + use std::option::Option::Some as S; let d = S(&temp()); let e = X(&temp()); let f = Some(Ok::<_, ()>(std::borrow::Cow::Borrowed(if true { @@ -31,6 +31,6 @@ fn main() { panic!() }))); let some = Some; // Turn the ctor into a regular function. - let g = some(&temp()); //~ERROR temporary value dropped while borrowe + let g = some(&temp()); //~ERROR temporary value dropped while borrowed println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); } diff --git a/tests/ui/panic-runtime/auxiliary/needs-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-abort.rs index 21f862e4b43..cba4907dbb6 100644 --- a/tests/ui/panic-runtime/auxiliary/needs-abort.rs +++ b/tests/ui/panic-runtime/auxiliary/needs-abort.rs @@ -1,5 +1,7 @@ //@ compile-flags:-C panic=abort //@ no-prefer-dynamic +#![feature(no_core)] #![crate_type = "rlib"] #![no_std] +#![no_core] diff --git a/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs new file mode 100644 index 00000000000..4a41d16faa0 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs @@ -0,0 +1,7 @@ +//@ compile-flags:-C panic=immediate-abort -Zunstable-options +//@ no-prefer-dynamic + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_std] +#![no_core] diff --git a/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs new file mode 100644 index 00000000000..295876fec52 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs @@ -0,0 +1,18 @@ +//@ compile-flags:-C panic=unwind +//@ no-prefer-dynamic +//@ add-core-stubs + +#![crate_type = "rlib"] +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate minicore; + +extern "C-unwind" fn foo() {} + +#[inline] +fn bar() { + let ptr: extern "C-unwind" fn() = foo; + ptr(); +} diff --git a/tests/ui/panic-runtime/bad-panic-flag1.rs b/tests/ui/panic-runtime/bad-panic-flag1.rs index 117935847cb..575e30f785c 100644 --- a/tests/ui/panic-runtime/bad-panic-flag1.rs +++ b/tests/ui/panic-runtime/bad-panic-flag1.rs @@ -2,4 +2,4 @@ fn main() {} -//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected +//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected diff --git a/tests/ui/panic-runtime/bad-panic-flag1.stderr b/tests/ui/panic-runtime/bad-panic-flag1.stderr index 013373c6f93..c30598bba53 100644 --- a/tests/ui/panic-runtime/bad-panic-flag1.stderr +++ b/tests/ui/panic-runtime/bad-panic-flag1.stderr @@ -1,2 +1,2 @@ -error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected +error: incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected diff --git a/tests/ui/panic-runtime/bad-panic-flag2.rs b/tests/ui/panic-runtime/bad-panic-flag2.rs index b5d0442a033..4e34da217d7 100644 --- a/tests/ui/panic-runtime/bad-panic-flag2.rs +++ b/tests/ui/panic-runtime/bad-panic-flag2.rs @@ -2,4 +2,4 @@ fn main() {} -//~? ERROR codegen option `panic` requires either `unwind` or `abort` +//~? ERROR codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort` diff --git a/tests/ui/panic-runtime/bad-panic-flag2.stderr b/tests/ui/panic-runtime/bad-panic-flag2.stderr index 6ab94ea704d..c8d12749c5d 100644 --- a/tests/ui/panic-runtime/bad-panic-flag2.stderr +++ b/tests/ui/panic-runtime/bad-panic-flag2.stderr @@ -1,2 +1,2 @@ -error: codegen option `panic` requires either `unwind` or `abort` (C panic=<value>) +error: codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort` (C panic=<value>) diff --git a/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs b/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs new file mode 100644 index 00000000000..94dc7c5671e --- /dev/null +++ b/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs @@ -0,0 +1,15 @@ +//@ build-fail +//@ aux-build:needs-unwind.rs +//@ compile-flags:-C panic=immediate-abort -Zunstable-options +//@ no-prefer-dynamic + +extern crate needs_unwind; + +// immediate-abort does not require any panic runtime, so trying to build a binary crate with +// panic=immediate-abort and the precompiled sysroot will fail to link, because no panic runtime +// provides the panic entrypoints used by sysroot crates. +// This test ensures that we get a clean compile error instead of a linker error. + +fn main() {} + +//~? ERROR the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort` diff --git a/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr b/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr new file mode 100644 index 00000000000..bd6bdd8b667 --- /dev/null +++ b/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr @@ -0,0 +1,4 @@ +error: the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort` + +error: aborting due to 1 previous error + diff --git a/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs b/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs new file mode 100644 index 00000000000..78977c60be9 --- /dev/null +++ b/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs @@ -0,0 +1,21 @@ +//@ build-fail +//@ aux-build:needs-abort.rs +//@ compile-flags:-Cpanic=immediate-abort -Zunstable-options +//@ no-prefer-dynamic +//@ add-core-stubs +//@ core-stubs-compile-flags: -Cpanic=immediate-abort -Zunstable-options + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +extern crate minicore; +extern crate needs_abort; + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + 0 +} + +//~? ERROR the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` diff --git a/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr b/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr new file mode 100644 index 00000000000..65a26b676b9 --- /dev/null +++ b/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` + +error: aborting due to 1 previous error + diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs b/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs new file mode 100644 index 00000000000..1c5f597a3f9 --- /dev/null +++ b/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs @@ -0,0 +1,20 @@ +//@ build-fail +//@ aux-build:needs-immediate-abort.rs +//@ compile-flags:-C panic=abort +//@ no-prefer-dynamic +//@ add-core-stubs +//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +extern crate minicore; +extern crate needs_immediate_abort; + +extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 { + 0 +} + +//~? ERROR the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr b/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr new file mode 100644 index 00000000000..8dcf120cb9f --- /dev/null +++ b/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` + +error: aborting due to 1 previous error + diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs new file mode 100644 index 00000000000..24d521230d4 --- /dev/null +++ b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs @@ -0,0 +1,20 @@ +//@ build-fail +//@ needs-unwind +//@ aux-build:needs-immediate-abort.rs +//@ no-prefer-dynamic +//@ add-core-stubs +//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +extern crate minicore; +extern crate needs_immediate_abort; + +extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 { + 0 +} + +//~? ERROR the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort` diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr new file mode 100644 index 00000000000..740fc80a77d --- /dev/null +++ b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr @@ -0,0 +1,4 @@ +error: the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort` + +error: aborting due to 1 previous error + diff --git a/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs new file mode 100644 index 00000000000..5aec028a46c --- /dev/null +++ b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs @@ -0,0 +1,21 @@ +//@ build-fail +//@ aux-build:needs-unwind-immediate-abort.rs +//@ compile-flags:-C panic=immediate-abort -Zunstable-options +//@ no-prefer-dynamic +//@ add-core-stubs +//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort + +#![feature(no_core)] +#![no_std] +#![no_main] +#![no_core] + +extern crate minicore; +extern crate needs_unwind_immediate_abort; + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + 0 +} + +//~? ERROR the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` diff --git a/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr new file mode 100644 index 00000000000..8b3747d644f --- /dev/null +++ b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort` + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs index 58e1d006433..adedba4ebca 100644 --- a/tests/ui/proc-macro/panic-abort.rs +++ b/tests/ui/proc-macro/panic-abort.rs @@ -2,4 +2,4 @@ //@ force-host //@ check-pass -//~? WARN building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic +//~? WARN building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic diff --git a/tests/ui/proc-macro/panic-abort.stderr b/tests/ui/proc-macro/panic-abort.stderr index a6e18614f8f..3dd75768bc4 100644 --- a/tests/ui/proc-macro/panic-abort.stderr +++ b/tests/ui/proc-macro/panic-abort.stderr @@ -1,4 +1,4 @@ -warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic +warning: building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic warning: 1 warning emitted diff --git a/tests/ui/suggestions/incorrect-variant-literal.svg b/tests/ui/suggestions/incorrect-variant-literal.svg index 2cab1f4b60f..4b952325cf7 100644 --- a/tests/ui/suggestions/incorrect-variant-literal.svg +++ b/tests/ui/suggestions/incorrect-variant-literal.svg @@ -1,7 +1,7 @@ <svg width="886px" height="9524px" xmlns="http://www.w3.org/2000/svg"> <style> .fg { fill: #AAAAAA } - .bg { background: #000000 } + .bg { fill: #000000 } .fg-ansi256-009 { fill: #FF5555 } .fg-ansi256-010 { fill: #55FF55 } .fg-ansi256-012 { fill: #5555FF } diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.rs b/tests/ui/suggestions/non_copy_move_out_of_tuple.rs new file mode 100644 index 00000000000..baf15dba33a --- /dev/null +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.rs @@ -0,0 +1,8 @@ +// Regression test for #146537. + +struct NonCopy; +fn main() { + let tuple = &(NonCopy,); + let b: NonCopy; + (b,) = *tuple; //~ ERROR: cannot move out of `tuple.0` which is behind a shared reference [E0507] +} diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr new file mode 100644 index 00000000000..62f24324fcc --- /dev/null +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -0,0 +1,26 @@ +error[E0507]: cannot move out of `tuple.0` which is behind a shared reference + --> $DIR/non_copy_move_out_of_tuple.rs:7:12 + | +LL | (b,) = *tuple; + | - ^^^^^^ + | | + | data moved here + | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait + | +note: if `NonCopy` implemented `Clone`, you could clone the value + --> $DIR/non_copy_move_out_of_tuple.rs:3:1 + | +LL | struct NonCopy; + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | (b,) = *tuple; + | - you could clone this value +help: consider removing the dereference here + | +LL - (b,) = *tuple; +LL + (b,) = tuple; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs index 6567f275240..2f108daf1e5 100644 --- a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs +++ b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver //@ check-pass -// Fixes a regression in icu_provider_adaptors where we weren't normalizing the +// Fixes a regression in icu_provider_adapters where we weren't normalizing the // return type of a function type before performing a `Ty::builtin_deref` call, // leading to an ICE. diff --git a/tests/ui/type-inference/box_has_sigdrop.rs b/tests/ui/type-inference/box_has_sigdrop.rs new file mode 100644 index 00000000000..3e801197a78 --- /dev/null +++ b/tests/ui/type-inference/box_has_sigdrop.rs @@ -0,0 +1,9 @@ +//@ should-fail +//@ compile-flags: -Wrust-2021-incompatible-closure-captures +// Inference, canonicalization, and significant drops should work nicely together. +// Related issue: #86868 + +fn main() { + let mut state = 0; + Box::new(move || state) +} diff --git a/tests/ui/type-inference/box_has_sigdrop.stderr b/tests/ui/type-inference/box_has_sigdrop.stderr new file mode 100644 index 00000000000..b61b6322c10 --- /dev/null +++ b/tests/ui/type-inference/box_has_sigdrop.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/box_has_sigdrop.rs:8:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | let mut state = 0; +LL | Box::new(move || state) + | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `Box<{closure@box_has_sigdrop.rs:8:14}>` + | + = note: expected unit type `()` + found struct `Box<{closure@$DIR/box_has_sigdrop.rs:8:14: 8:21}>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-inference/has_sigdrop.rs b/tests/ui/type-inference/dropper_has_sigdrop.rs index c3d835cfe16..c3d835cfe16 100644 --- a/tests/ui/type-inference/has_sigdrop.rs +++ b/tests/ui/type-inference/dropper_has_sigdrop.rs |
