diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index be0db12b52f3a..f62b8e542652b 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -94,11 +94,11 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - name: download Cargo.lock from update job - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: Cargo-lock - name: download cargo-update log from update job - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: cargo-updates diff --git a/Cargo.lock b/Cargo.lock index 58793fc90e707..2f05b186b3fc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,15 +300,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "2.10.0" @@ -2106,18 +2097,19 @@ dependencies = [ [[package]] name = "ipc-channel" -version = "0.20.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180" +checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61" dependencies = [ - "bincode", "crossbeam-channel", - "fnv", "libc", "mio", + "postcard", "rand 0.9.2", - "serde", + "rustc-hash 2.1.1", + "serde_core", "tempfile", + "thiserror 2.0.17", "uuid", "windows 0.61.3", ] diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs index 5b61e83b5e6bd..85708273a409b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs @@ -1,16 +1,14 @@ use rustc_feature::AttributeStability; use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; -use rustc_session::lint::builtin::{ - MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, -}; +use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::{Symbol, sym}; +use crate::attributes::prelude::Allow; use crate::attributes::{OnDuplicate, SingleAttributeParser}; use crate::context::AcceptContext; -use crate::diagnostics::IncorrectDoNotRecommendLocation; use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use crate::target_checking::AllowedTargets; use crate::{AttributeTemplate, template}; pub(crate) struct DoNotRecommendParser; @@ -18,7 +16,8 @@ impl SingleAttributeParser for DoNotRecommendParser { const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; // "Allowed" on any target, noop on all but trait impls - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Impl { of_trait: true })]); const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -32,16 +31,6 @@ impl SingleAttributeParser for DoNotRecommendParser { ); } - if !matches!(cx.target, Target::Impl { of_trait: true }) { - let target_span = cx.target_span; - cx.emit_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - IncorrectDoNotRecommendLocation { target_span }, - attr_span, - ); - return None; - } - Some(AttributeKind::DoNotRecommend) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs index 42159e8057f14..dc8260ae944ef 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs @@ -1,10 +1,8 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::diagnostic::Directive; -use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; -use crate::diagnostics::DiagnosticOnConstOnlyForTraitImpls; #[derive(Default)] pub(crate) struct OnConstParser { span: Option, @@ -26,18 +24,6 @@ impl AttributeParser for OnConstParser { let span = cx.attr_span; this.span = Some(span); - // FIXME(mejrs) no constness field on `Target`, - // so non-constness is still checked in check_attr.rs - if !matches!(cx.target, Target::Impl { of_trait: true }) { - let target_span = cx.target_span; - cx.emit_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - DiagnosticOnConstOnlyForTraitImpls { target_span }, - span, - ); - return; - } - let mode = Mode::DiagnosticOnConst; let Some(items) = parse_list(cx, args, mode) else { return }; @@ -51,7 +37,11 @@ impl AttributeParser for OnConstParser { // "Allowed" on all targets; noop on anything but non-const trait impls; // this linted on in parser. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + // FIXME(mejrs) no constness field on `Target`, + // so non-constness is still checked in check_attr.rs + Allow(Target::Impl { of_trait: true }), + ]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs index 38d2e7f8f53e6..ec77ede4127f5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs @@ -1,14 +1,12 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::AttributeKind; -use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::sym; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; use crate::context::AcceptContext; -use crate::diagnostics::DiagnosticOnMoveOnlyForAdt; use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use crate::target_checking::AllowedTargets; use crate::template; #[derive(Default)] @@ -28,11 +26,6 @@ impl OnMoveParser { let span = cx.attr_span; self.span = Some(span); - if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) { - cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnMoveOnlyForAdt, span); - return; - } - let Some(items) = parse_list(cx, args, mode) else { return }; if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) { @@ -50,8 +43,11 @@ impl AttributeParser for OnMoveParser { }, )]; - // "Allowed" for all targets but noop if used on not-adt. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::Union), + ]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(_span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs index a1d7ff2004c2c..d5636b23a09b1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs @@ -1,14 +1,12 @@ use rustc_hir::attrs::AttributeKind; -use rustc_lint_defs::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::sym; use crate::attributes::AttributeStability; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; use crate::context::AcceptContext; -use crate::diagnostics::DiagnosticOnTypeErrorOnlyForAdt; use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use crate::target_checking::AllowedTargets; use crate::template; #[derive(Default)] @@ -26,11 +24,6 @@ impl OnTypeErrorParser { let span = cx.attr_span; self.span = Some(span); - if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) { - cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnTypeErrorOnlyForAdt, span); - return; - } - let Some(items) = parse_list(cx, args, mode) else { return }; if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) { @@ -49,7 +42,11 @@ impl AttributeParser for OnTypeErrorParser { }, )]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::Union), + ]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs index b06bf88dc7ab8..86a96f7093587 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs @@ -1,10 +1,8 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::diagnostic::Directive; -use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; -use crate::diagnostics::DiagnosticOnUnimplementedOnlyForTraits; #[derive(Default)] pub(crate) struct OnUnimplementedParser { @@ -17,15 +15,6 @@ impl OnUnimplementedParser { let span = cx.attr_span; self.span = Some(span); - if !matches!(cx.target, Target::Trait) { - cx.emit_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - DiagnosticOnUnimplementedOnlyForTraits, - span, - ); - return; - } - let Some(items) = parse_list(cx, args, mode) else { return }; if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) { @@ -56,8 +45,8 @@ impl AttributeParser for OnUnimplementedParser { }, ), ]; - //FIXME attribute is not parsed for non-traits but diagnostics are issued in `check_attr.rs` - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Trait)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(_span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs index f1e4b8415185e..fc05ae9150d15 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs @@ -1,11 +1,8 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::diagnostic::Directive; -use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; -use crate::ShouldEmit; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; -use crate::diagnostics::DiagnosticOnUnknownInvalidTarget; #[derive(Default)] pub(crate) struct OnUnknownParser { @@ -25,20 +22,6 @@ impl OnUnknownParser { let span = cx.attr_span; self.span = Some(span); - // At early parsing we get passed `Target::Crate` regardless of the item we're on. - // Therefore, only do target checking if we can emit. - let early = matches!(cx.should_emit, ShouldEmit::Nothing); - - if !early && !matches!(cx.target, Target::Use | Target::Mod | Target::Crate) { - let target_span = cx.target_span; - cx.emit_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - DiagnosticOnUnknownInvalidTarget { target_span }, - span, - ); - return; - } - let Some(items) = parse_list(cx, args, mode) else { return }; if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) { @@ -57,7 +40,11 @@ impl AttributeParser for OnUnknownParser { }, )]; // "Allowed" for all targets, but noop for all but use statements. - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Use), + Allow(Target::Mod), + Allow(Target::Crate), + ]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(_span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs index 17b9fcd52d225..44975cd49c93f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs @@ -1,10 +1,8 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::diagnostic::Directive; -use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; -use crate::diagnostics::DiagnosticOnUnmatchedArgsOnlyForMacros; #[derive(Default)] pub(crate) struct OnUnmatchedArgsParser { @@ -25,15 +23,6 @@ impl AttributeParser for OnUnmatchedArgsParser { let span = cx.attr_span; this.span = Some(span); - if !matches!(cx.target, Target::MacroDef) { - cx.emit_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - DiagnosticOnUnmatchedArgsOnlyForMacros, - span, - ); - return; - } - let mode = Mode::DiagnosticOnUnmatchedArgs; let Some(items) = parse_list(cx, args, mode) else { return }; @@ -44,7 +33,8 @@ impl AttributeParser for OnUnmatchedArgsParser { }, )]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::MacroDef)]); fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { if let Some(_span) = self.span { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 8ffd2281a582f..b22fe88a4de3d 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -279,45 +279,6 @@ pub(crate) struct UnknownCrateTypesSuggestion { pub snippet: Symbol, } -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_const]` can only be applied to non-const trait implementations")] -pub(crate) struct DiagnosticOnConstOnlyForTraitImpls { - #[label("not a trait implementation")] - pub target_span: Span, -} - -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")] -pub(crate) struct DiagnosticOnMoveOnlyForAdt; - -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_unimplemented]` can only be applied to trait definitions")] -pub(crate) struct DiagnosticOnUnimplementedOnlyForTraits; - -#[derive(Diagnostic)] -#[diag( - "`#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations" -)] -pub(crate) struct DiagnosticOnUnknownInvalidTarget { - #[label("not an import or module")] - pub target_span: Span, -} - -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_unmatched_args]` can only be applied to macro definitions")] -pub(crate) struct DiagnosticOnUnmatchedArgsOnlyForMacros; - -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_type_error]` can only be applied to enums, structs or unions")] -pub(crate) struct DiagnosticOnTypeErrorOnlyForAdt; - -#[derive(Diagnostic)] -#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")] -pub(crate) struct IncorrectDoNotRecommendLocation { - #[label("not a trait implementation")] - pub target_span: Span, -} - #[derive(Diagnostic)] #[diag("malformed `doc` attribute input")] #[warning( diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 1c2716c911b7b..9903c6aa68d01 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -129,6 +129,7 @@ impl<'sess> AttributeParser<'sess> { let allowed_targets = allowed_targets.allowed_targets(); let (applied, only) = allowed_targets_applied(allowed_targets, cx.target, cx.features); + let is_diagnostic_attr = cx.attr_path.segments[0] == sym::diagnostic; let diag = InvalidTarget { span: cx.attr_span.clone(), @@ -138,7 +139,7 @@ impl<'sess> AttributeParser<'sess> { applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()), attribute_args, help: Self::target_checking_help(attribute_args, cx), - previously_accepted: matches!(result, AllowedResult::Warn), + previously_accepted: matches!(result, AllowedResult::Warn) && !is_diagnostic_attr, on_macro_call: matches!(cx.target, Target::MacroCall), }; @@ -156,6 +157,8 @@ impl<'sess> AttributeParser<'sess> { .contains(&cx.target) { rustc_session::lint::builtin::USELESS_DEPRECATED + } else if is_diagnostic_attr { + rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES } else { rustc_session::lint::builtin::UNUSED_ATTRIBUTES }; diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index d40340e4d8c09..bde285c5c18fd 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1862,7 +1862,7 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, Symbol } let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); - let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let proc_macro_decls_name = rustc_session::generate_proc_macro_decls_symbol(stable_crate_id); vec![(proc_macro_decls_name, SymbolExportKind::Data)] } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index cb3d1b6d67487..dd063f5425511 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,10 +1,8 @@ //! Validates all used crates and extern libraries and loads their metadata use std::collections::BTreeMap; -use std::error::Error; use std::path::Path; use std::str::FromStr; -use std::time::Duration; use std::{cmp, env, iter}; use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, AllocatorKind, global_fn_name}; @@ -15,7 +13,6 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::UnordMap; use rustc_expand::base::SyntaxExtension; -use rustc_fs_util::try_canonicalize; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId}; use rustc_hir::definitions::Definitions; @@ -653,7 +650,7 @@ impl CStore { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(tcx.sess, dlsym_dylib, dlsym_root.stable_crate_id())?) + Some(self.dlsym_proc_macros(dlsym_dylib, dlsym_root.stable_crate_id())?) } else { None }; @@ -948,31 +945,10 @@ impl CStore { fn dlsym_proc_macros( &self, - sess: &Session, path: &Path, stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacroClient], CrateError> { - let sym_name = sess.generate_proc_macro_decls_symbol(stable_crate_id); - debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); - - unsafe { - // FIXME(bjorn3) this depends on the unstable slice memory layout - let result = load_symbol_from_dylib::<*const &[ProcMacroClient]>(path, &sym_name); - match result { - Ok(result) => { - debug!("loaded dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); - Ok(*result) - } - Err(err) => { - debug!( - "failed to dlsym proc_macros {} for symbol `{}`", - path.display(), - sym_name - ); - Err(err.into()) - } - } - } + Ok(crate::host_dylib::dlsym_proc_macros(path, stable_crate_id)?) } fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { @@ -1415,117 +1391,3 @@ fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec { visit::walk_crate(&mut f, krate); f.spans } - -fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String { - e.sources().map(|e| format!(": {e}")).collect() -} - -fn attempt_load_dylib(path: &Path) -> Result { - #[cfg(target_os = "aix")] - if let Some(ext) = path.extension() - && ext.eq("a") - { - // On AIX, we ship all libraries as .a big_af archive - // the expected format is lib.a(libname.so) for the actual - // dynamic library - let library_name = path.file_stem().expect("expect a library name"); - let mut archive_member = std::ffi::OsString::from("a("); - archive_member.push(library_name); - archive_member.push(".so)"); - let new_path = path.with_extension(archive_member); - - // On AIX, we need RTLD_MEMBER to dlopen an archived shared - let flags = libc::RTLD_LAZY | libc::RTLD_LOCAL | libc::RTLD_MEMBER; - return unsafe { libloading::os::unix::Library::open(Some(&new_path), flags) } - .map(|lib| lib.into()); - } - - unsafe { libloading::Library::new(&path) } -} - -// On Windows the compiler would sometimes intermittently fail to open the -// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the -// system still holds a lock on the file, so we retry a few times before calling it -// an error. -fn load_dylib(path: &Path, max_attempts: usize) -> Result { - assert!(max_attempts > 0); - - let mut last_error = None; - - for attempt in 0..max_attempts { - debug!("Attempt to load proc-macro `{}`.", path.display()); - match attempt_load_dylib(path) { - Ok(lib) => { - if attempt > 0 { - debug!( - "Loaded proc-macro `{}` after {} attempts.", - path.display(), - attempt + 1 - ); - } - return Ok(lib); - } - Err(err) => { - // Only try to recover from this specific error. - if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { - debug!("Failed to load proc-macro `{}`. Not retrying", path.display()); - let err = format_dlopen_err(&err); - // We include the path of the dylib in the error ourselves, so - // if it's in the error, we strip it. - if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) { - return Err(err.to_string()); - } - return Err(err); - } - - last_error = Some(err); - std::thread::sleep(Duration::from_millis(100)); - debug!("Failed to load proc-macro `{}`. Retrying.", path.display()); - } - } - } - - debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts); - - let last_error = last_error.unwrap(); - let message = if let Some(src) = last_error.source() { - format!("{} ({src}) (retried {max_attempts} times)", format_dlopen_err(&last_error)) - } else { - format!("{} (retried {max_attempts} times)", format_dlopen_err(&last_error)) - }; - Err(message) -} - -pub enum DylibError { - DlOpen(String, String), - DlSym(String, String), -} - -impl From for CrateError { - fn from(err: DylibError) -> CrateError { - match err { - DylibError::DlOpen(path, err) => CrateError::DlOpen(path, err), - DylibError::DlSym(path, err) => CrateError::DlSym(path, err), - } - } -} - -pub unsafe fn load_symbol_from_dylib( - path: &Path, - sym_name: &str, -) -> Result { - // Make sure the path contains a / or the linker will search for it. - let path = try_canonicalize(path).unwrap(); - let lib = - load_dylib(&path, 5).map_err(|err| DylibError::DlOpen(path.display().to_string(), err))?; - - let sym = unsafe { lib.get::(sym_name.as_bytes()) } - .map_err(|err| DylibError::DlSym(path.display().to_string(), format_dlopen_err(&err)))?; - - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can make things that will live arbitrarily long. - let sym = unsafe { sym.into_raw() }; - std::mem::forget(lib); - - Ok(*sym) -} diff --git a/compiler/rustc_metadata/src/host_dylib.rs b/compiler/rustc_metadata/src/host_dylib.rs new file mode 100644 index 0000000000000..9bd2a57fcd285 --- /dev/null +++ b/compiler/rustc_metadata/src/host_dylib.rs @@ -0,0 +1,147 @@ +use std::error::Error; +use std::path::Path; +use std::time::Duration; + +use rustc_fs_util::try_canonicalize; +use rustc_proc_macro::bridge::client::Client as ProcMacroClient; +use rustc_session::StableCrateId; +use tracing::debug; + +use crate::locator::CrateError; + +fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String { + e.sources().map(|e| format!(": {e}")).collect() +} + +fn attempt_load_dylib(path: &Path) -> Result { + #[cfg(target_os = "aix")] + if let Some(ext) = path.extension() + && ext.eq("a") + { + // On AIX, we ship all libraries as .a big_af archive + // the expected format is lib.a(libname.so) for the actual + // dynamic library + let library_name = path.file_stem().expect("expect a library name"); + let mut archive_member = std::ffi::OsString::from("a("); + archive_member.push(library_name); + archive_member.push(".so)"); + let new_path = path.with_extension(archive_member); + + // On AIX, we need RTLD_MEMBER to dlopen an archived shared + let flags = libc::RTLD_LAZY | libc::RTLD_LOCAL | libc::RTLD_MEMBER; + return unsafe { libloading::os::unix::Library::open(Some(&new_path), flags) } + .map(|lib| lib.into()); + } + + unsafe { libloading::Library::new(&path) } +} + +// On Windows the compiler would sometimes intermittently fail to open the +// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the +// system still holds a lock on the file, so we retry a few times before calling it +// an error. +fn load_dylib(path: &Path, max_attempts: usize) -> Result { + assert!(max_attempts > 0); + + let mut last_error = None; + + for attempt in 0..max_attempts { + debug!("Attempt to load proc-macro `{}`.", path.display()); + match attempt_load_dylib(path) { + Ok(lib) => { + if attempt > 0 { + debug!( + "Loaded proc-macro `{}` after {} attempts.", + path.display(), + attempt + 1 + ); + } + return Ok(lib); + } + Err(err) => { + // Only try to recover from this specific error. + if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { + debug!("Failed to load proc-macro `{}`. Not retrying", path.display()); + let err = format_dlopen_err(&err); + // We include the path of the dylib in the error ourselves, so + // if it's in the error, we strip it. + if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) { + return Err(err.to_string()); + } + return Err(err); + } + + last_error = Some(err); + std::thread::sleep(Duration::from_millis(100)); + debug!("Failed to load proc-macro `{}`. Retrying.", path.display()); + } + } + } + + debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts); + + let last_error = last_error.unwrap(); + let message = if let Some(src) = last_error.source() { + format!("{} ({src}) (retried {max_attempts} times)", format_dlopen_err(&last_error)) + } else { + format!("{} (retried {max_attempts} times)", format_dlopen_err(&last_error)) + }; + Err(message) +} + +pub enum DylibError { + DlOpen(String, String), + DlSym(String, String), +} + +impl From for CrateError { + fn from(err: DylibError) -> CrateError { + match err { + DylibError::DlOpen(path, err) => CrateError::DlOpen(path, err), + DylibError::DlSym(path, err) => CrateError::DlSym(path, err), + } + } +} + +pub unsafe fn load_symbol_from_dylib( + path: &Path, + sym_name: &str, +) -> Result { + // Make sure the path contains a / or the linker will search for it. + let path = try_canonicalize(path).unwrap(); + let lib = + load_dylib(&path, 5).map_err(|err| DylibError::DlOpen(path.display().to_string(), err))?; + + let sym = unsafe { lib.get::(sym_name.as_bytes()) } + .map_err(|err| DylibError::DlSym(path.display().to_string(), format_dlopen_err(&err)))?; + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + let sym = unsafe { sym.into_raw() }; + std::mem::forget(lib); + + Ok(*sym) +} + +pub(crate) fn dlsym_proc_macros( + path: &Path, + stable_crate_id: StableCrateId, +) -> Result<&'static [ProcMacroClient], DylibError> { + let sym_name = rustc_session::generate_proc_macro_decls_symbol(stable_crate_id); + debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); + + unsafe { + // FIXME(bjorn3) this depends on the unstable slice memory layout + let result = crate::load_symbol_from_dylib::<*const &[ProcMacroClient]>(path, &sym_name); + match result { + Ok(result) => { + debug!("loaded dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); + Ok(*result) + } + Err(err) => { + debug!("failed to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); + Err(err.into()) + } + } + } +} diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index e782414c62a0a..840b1c4c6fa2f 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -17,6 +17,7 @@ pub use rmeta::provide; mod dependency_format; mod eii; mod foreign_modules; +mod host_dylib; mod native_libs; mod rmeta; @@ -25,8 +26,8 @@ pub mod diagnostics; pub mod fs; pub mod locator; -pub use creader::{DylibError, load_symbol_from_dylib}; pub use fs::{METADATA_FILENAME, emit_wrapper_file}; +pub use host_dylib::{DylibError, load_symbol_from_dylib}; pub use native_libs::{ NativeLibSearchFallback, find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, walk_native_lib_search_dirs, diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 321274243a857..874d4812502e6 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,7 +213,7 @@ //! metadata::locator or metadata::creader for all the juicy details! use std::borrow::Cow; -use std::io::{Result as IoResult, Write}; +use std::io::{self, Result as IoResult, Write}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt}; @@ -224,6 +224,7 @@ use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; use rustc_data_structures::svh::Svh; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_fs_util::try_canonicalize; +use rustc_proc_macro::bridge::client::Client as ProcMacroClient; use rustc_session::cstore::CrateSource; use rustc_session::filesearch::FileSearch; use rustc_session::search_paths::PathKind; @@ -821,7 +822,7 @@ fn get_metadata_section<'p>( crate_name: Option, ) -> Result> { if !filename.exists() { - return Err(MetadataError::NotPresent(filename.into())); + return Err(MetadataError::NotPresent(filename)); } let raw_bytes = match flavor { CrateFlavor::Rlib => { @@ -978,18 +979,29 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor { } } -/// A function to get information about all macros inside a proc-macro crate. +/// A function to fetch about all macros inside a proc-macro crate. /// /// Used by rust-analyzer-proc-macro-srv. -pub fn get_proc_macro_info<'p>( +pub fn get_proc_macros( target: &Target, - path: &'p Path, + path: &Path, metadata_loader: &dyn MetadataLoader, cfg_version: &'static str, -) -> Result, MetadataError<'p>> { +) -> IoResult> { let metadata = - get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)?; - Ok(metadata.get_proc_macro_info()) + get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None) + .map_err(|err| io::Error::other(err.to_string()))?; + let stable_crate_id = metadata.get_root().stable_crate_id(); + + let clients = crate::host_dylib::dlsym_proc_macros(path, stable_crate_id).map_err(|err| { + let (crate::DylibError::DlOpen(path, err) | crate::DylibError::DlSym(path, err)) = err; + io::Error::other(format!("{path}{err}")) + })?; + + let proc_macro_info = metadata.get_proc_macro_info(); + assert_eq!(proc_macro_info.len(), clients.len()); + + Ok(clients.into_iter().copied().zip(proc_macro_info).collect()) } // ------------------------------------------ Error reporting ------------------------------------- @@ -1039,9 +1051,9 @@ pub(crate) enum CrateError { } #[derive(Debug)] -pub enum MetadataError<'a> { +pub(crate) enum MetadataError<'a> { /// The file was missing. - NotPresent(Cow<'a, Path>), + NotPresent(&'a Path), /// The file was present and invalid. LoadFailure(String), /// The file was present, but compiled with a different rustc version. diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 74e5fc6f34579..0076e3ed4167c 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -76,30 +76,24 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { _ => unreachable!(), } - // delete comparison statement if it the value being switched on was moved, which means - // it can not be used later on - if opt.can_remove_bin_op_stmt { - bb.statements[opt.bin_op_stmt_idx].make_nop(true); - } else { - // if the integer being compared to a const integral is being moved into the - // comparison, e.g `_2 = Eq(move _3, const 'x');` - // we want to avoid making a double move later on in the switchInt on _3. - // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, - // we convert the move in the comparison statement to a copy. - - // unwrap is safe as we know this statement is an assign - let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap(); - - use Operand::*; - match rhs { - Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => { - *left = Copy(opt.to_switch_on); - } - Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => { - *right = Copy(opt.to_switch_on); - } - _ => (), + // if the integer being compared to a const integral is being moved into the + // comparison, e.g `_2 = Eq(move _3, const 'x');` + // we want to avoid making a double move later on in the switchInt on _3. + // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, + // we convert the move in the comparison statement to a copy. + + // unwrap is safe as we know this statement is an assign + let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap(); + + use Operand::*; + match rhs { + Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => { + *left = Copy(opt.to_switch_on); + } + Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => { + *right = Copy(opt.to_switch_on); } + _ => (), } let terminator = bb.terminator(); @@ -184,7 +178,6 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> { Some(OptimizationInfo { bin_op_stmt_idx: stmt_idx, bb_idx, - can_remove_bin_op_stmt: discr.is_move(), to_switch_on, branch_value_scalar, branch_value_ty, @@ -235,11 +228,8 @@ fn find_branch_value_info<'tcx>( struct OptimizationInfo<'tcx> { /// Basic block to apply the optimization bb_idx: BasicBlock, - /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be - /// removed - i.e the statement is used later on + /// Statement index of Eq/Ne assignment bin_op_stmt_idx: usize, - /// Can remove Eq/Ne assignment - can_remove_bin_op_stmt: bool, /// Place that needs to be switched on. This place is of type integral to_switch_on: Place<'tcx>, /// Constant to use in switch target value diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4cf152136bf3a..15a87771056c4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -420,10 +420,6 @@ impl Session { self.target.debuginfo_kind == DebuginfoKind::Dwarf } - pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String { - format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64()) - } - pub fn target_filesearch(&self) -> &filesearch::FileSearch { &self.target_filesearch } @@ -1149,6 +1145,10 @@ pub fn build_session( sess } +pub fn generate_proc_macro_decls_symbol(stable_crate_id: StableCrateId) -> String { + format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64()) +} + /// Validate command line arguments with a `Session`. /// /// If it is useful to have a Session available already for validating a commandline argument, you diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 475b0827a53d3..c3b02eb46ba1e 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -165,7 +165,7 @@ fn compute_symbol_name<'tcx>( if let Some(def_id) = def_id.as_local() { if tcx.proc_macro_decls_static(()) == Some(def_id) { let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); - return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); + return rustc_session::generate_proc_macro_decls_symbol(stable_crate_id); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index ff62defea38f6..53eebfd377171 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -40,6 +40,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if trait_pred.polarity() != ty::PredicatePolarity::Positive { return CustomDiagnostic::default(); } + // This is needed as `on_unimplemented` is currently not allowed on trait aliases, + // but the "not allowed" is a warning, and this check ensures the attribute has no effect + if self.tcx.is_trait_alias(trait_pred.def_id()) { + return CustomDiagnostic::default(); + } let (filter_options, format_args) = self.on_unimplemented_components(trait_pred, obligation, long_ty_path); if let Some(command) = find_attr!(self.tcx, trait_pred.def_id(), OnUnimplemented {directive, ..} => directive.as_deref()).flatten() { diff --git a/library/backtrace b/library/backtrace index 28ec93b503bf0..d902726a1dcdc 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit 28ec93b503bf0410745bc3d571bf3dc1caac3019 +Subproject commit d902726a1dcdc1e1c66f73d1162181b5423c645b diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 087a395a067f0..9891f54907c7c 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -169,7 +169,7 @@ pub fn prebuilt_llvm_config( generate_smart_stamp_hash( builder, &builder.config.src.join("src/llvm-project"), - builder.in_tree_llvm_info.sha().unwrap_or_default(), + &builder.llvm_cache_key(), ) }); @@ -999,7 +999,7 @@ impl Step for OmpOffload { generate_smart_stamp_hash( builder, &builder.config.src.join("src/llvm-project/offload"), - builder.in_tree_llvm_info.sha().unwrap_or_default(), + &builder.llvm_cache_key(), ) }); let stamp = BuildStamp::new(&out_dir).with_prefix("offload").add_stamp(smart_stamp_hash); @@ -1166,8 +1166,8 @@ impl Step for Enzyme { // Enzyme links against LLVM. If we update the LLVM submodule libLLVM might get a new // version number, in which case Enzyme will now fail to find LLVM. By including the LLVM // hash into the Enzyme hash we force a rebuild of Enzyme when updating LLVM. - let enzyme_hash_input = builder.in_tree_llvm_info.sha().unwrap_or_default().to_owned() - + builder.enzyme_info.sha().unwrap_or_default(); + let enzyme_hash_input = + builder.llvm_cache_key() + builder.enzyme_info.sha().unwrap_or_default(); static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { @@ -1430,7 +1430,7 @@ impl Step for Sanitizers { generate_smart_stamp_hash( builder, &builder.config.src.join("src/llvm-project/compiler-rt"), - builder.in_tree_llvm_info.sha().unwrap_or_default(), + &builder.llvm_cache_key(), ) }); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 0dd6cd0d6fc3b..f7f708902c095 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -992,6 +992,140 @@ impl Step for StdarchVerify { } } +/// Runs stdarch's intrinsic-test binary crate to verify that Rust's `core::arch` +/// SIMD intrinsics produce the same results as their C counterparts. +/// +/// First runs the `intrinsic-test` binary, which generates C wrapper programs +/// and a Rust Cargo workspace. Then runs `cargo test` on that workspace +/// which compiles both versions and compares their outputs on random inputs. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct IntrinsicTest { + host: TargetSelection, +} + +impl Step for IntrinsicTest { + type Output = (); + const IS_HOST: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("library/stdarch/crates/intrinsic-test") + } + + fn make_run(run: RunConfig<'_>) { + let target = run.target; + if !target.contains("aarch64-unknown-linux") && !target.contains("x86_64-unknown-linux") { + return; + } + run.builder.ensure(IntrinsicTest { host: target }); + } + + fn run(self, builder: &Builder<'_>) { + let host = self.host; + + let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") { + let cpuid_def = + builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def"); + let sde_runner = format!( + "/intel-sde/sde64 -cpuid-in {} -rtm-mode full -tsx --", + cpuid_def.display() + ); + ( + builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"), + [ + builder + .src + .join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"), + builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"), + ], + "-I/usr/include/x86_64-linux-gnu/", + Some(sde_runner), + ) + } else if host.contains("aarch64-unknown-linux") { + ( + builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"), + [ + builder + .src + .join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"), + builder + .src + .join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"), + ], + "-I/usr/aarch64-linux-gnu/include/", + None, + ) + } else { + panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}"); + }; + + let out_dir = builder.out.join(host).join("intrinsic-test"); + t!(fs::create_dir_all(&out_dir)); + + let crates_link = out_dir.join("crates"); + if !crates_link.exists() { + t!( + helpers::symlink_dir( + &builder.config, + &builder.src.join("library/stdarch/crates"), + &crates_link + ), + format!("failed to symlink stdarch crates into {}", crates_link.display()) + ); + } + + let mut cmd = builder.tool_cmd(Tool::IntrinsicTest); + cmd.current_dir(&out_dir); + cmd.arg(&input_file); + cmd.arg("--target").arg(&*host.triple); + for skip in &skip_file { + cmd.arg("--skip").arg(skip); + } + cmd.arg("--sample-percentage").arg("10"); + cmd.arg("--cc-arg-style").arg("gcc"); + cmd.env("CC", builder.cc(host)); + cmd.env("CFLAGS", cflags); + // intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's + // managed binaries findable by prepending their dirs to PATH. + let rustfmt_path = builder.config.initial_rustfmt.clone().unwrap_or_else(|| { + eprintln!("intrinsic-test: rustfmt is required but not available on this channel"); + crate::exit!(1); + }); + + let mut path_dirs: Vec = Vec::new(); + if let Some(cargo_dir) = builder.initial_cargo.parent() { + path_dirs.push(cargo_dir.to_path_buf()); + } + if let Some(rustfmt_dir) = rustfmt_path.parent() { + path_dirs.push(rustfmt_dir.to_path_buf()); + } + let old_path = env::var_os("PATH").unwrap_or_default(); + let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path))) + .expect("could not build PATH for intrinsic-test"); + cmd.env("PATH", new_path); + cmd.run(builder); + + let tested_compiler = builder.compiler(builder.top_stage, host); + builder.std(tested_compiler, host); + let rustc = builder.rustc(tested_compiler); + + let manifest = out_dir.join("rust_programs/Cargo.toml"); + let mut cargo = command(&builder.initial_cargo); + cargo.arg("test"); + cargo.arg("--tests"); + cargo.arg("--manifest-path").arg(&manifest); + cargo.arg("--target").arg(&*host.triple); + cargo.arg("--profile").arg("release"); + cargo.env("CC", builder.cc(host)); + cargo.env("CFLAGS", cflags); + cargo.env("RUSTC", rustc); + cargo.env("RUSTC_BOOTSTRAP", "1"); + if let Some(runner) = sde_runner { + cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner); + } + cargo.run(builder); + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Clippy { compilers: RustcPrivateCompilers, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 144c75a02a5ee..cb65c08eb9f43 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -508,6 +508,7 @@ bootstrap_tool!( FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump"; OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"]; RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library; + IntrinsicTest, "library/stdarch/crates/intrinsic-test", "intrinsic-test"; ); /// These are the submodules that are required for rustbook to work due to diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap index f97bb839c1e73..ba1f6b3c940c3 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap @@ -21,3 +21,6 @@ expression: test library [Test] test::StdarchVerify targets: [x86_64-unknown-linux-gnu] - Set({test::library/stdarch/crates/stdarch-verify}) +[Test] test::IntrinsicTest + targets: [x86_64-unknown-linux-gnu] + - Set({test::library/stdarch/crates/intrinsic-test}) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 2e640220efd8e..6b2f526a8226d 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -911,6 +911,7 @@ impl<'a> Builder<'a> { test::Clippy, test::CompiletestTest, test::StdarchVerify, + test::IntrinsicTest, test::CrateRunMakeSupport, test::CrateBuildHelper, test::RustdocJSStd, @@ -1686,6 +1687,16 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler pub fn exec_ctx(&self) -> &ExecutionContext { &self.config.exec_ctx } + + /// When to rebuild LLVM. Currently includes the LLVM commit hash and the configuration from + /// bootstrap.toml. + pub(crate) fn llvm_cache_key(&self) -> String { + format!( + "sha={sha}\nkey={key}", + sha = self.in_tree_llvm_info.sha().unwrap_or_default(), + key = self.config.llvm_cache_key, + ) + } } /// Return qualified step name, e.g. `compile::Rustc`. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 5a9c7264c006f..0297907057ef9 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -156,6 +156,9 @@ pub struct Config { pub backtrace_on_ice: bool, // llvm codegen options + /// Key used to decide when to rebuild LLVM. + pub llvm_cache_key: String, + pub llvm_assertions: bool, pub llvm_tests: bool, pub llvm_enzyme: bool, @@ -595,6 +598,8 @@ impl Config { rustflags: rust_rustflags, } = toml.rust.unwrap_or_default(); + let llvm = toml.llvm.unwrap_or_default(); + let llvm_cache_key = llvm.cache_key(); let Llvm { optimize: llvm_optimize, thin_lto: llvm_thin_lto, @@ -625,7 +630,7 @@ impl Config { enable_warnings: llvm_enable_warnings, download_ci_llvm: llvm_download_ci_llvm, build_config: llvm_build_config, - } = toml.llvm.unwrap_or_default(); + } = llvm; let Dist { sign_folder: dist_sign_folder, @@ -1401,6 +1406,7 @@ impl Config { llvm_assertions, llvm_bitcode_linker_enabled: rust_llvm_bitcode_linker.unwrap_or(false), llvm_build_config: llvm_build_config.clone().unwrap_or(Default::default()), + llvm_cache_key, llvm_cflags, llvm_clang: llvm_clang.unwrap_or(false), llvm_clang_cl, diff --git a/src/bootstrap/src/core/config/toml/llvm.rs b/src/bootstrap/src/core/config/toml/llvm.rs index 5f08884e4ef71..e54c17c63aaae 100644 --- a/src/bootstrap/src/core/config/toml/llvm.rs +++ b/src/bootstrap/src/core/config/toml/llvm.rs @@ -43,6 +43,93 @@ define_config! { } } +impl Llvm { + /// A key that is used to determine whether LLVM should be rebuilt. + pub(crate) fn cache_key(&self) -> String { + let helper = || { + let mut key = String::with_capacity(512); + + let Self { + optimize, + thin_lto, + release_debuginfo, + assertions, + tests, + enzyme, + plugins, + static_libstdcpp, + libzstd, + ninja, + targets, + experimental_targets, + link_jobs: _, + link_shared, + version_suffix, + clang_cl, + cflags, + cxxflags, + ldflags, + use_libcxx, + use_linker, + allow_old_toolchain, + offload, + polly, + offload_clang_dir, + clang, + enable_warnings: _, + build_config, + download_ci_llvm: _, + } = self; + + use std::fmt::Write; + write!(key, "{:?}", optimize)?; + write!(key, "{:?}", thin_lto)?; + write!(key, "{:?}", release_debuginfo)?; + write!(key, "{:?}", assertions)?; + write!(key, "{:?}", tests)?; + write!(key, "{:?}", enzyme)?; + write!(key, "{:?}", plugins)?; + write!(key, "{:?}", static_libstdcpp)?; + write!(key, "{:?}", libzstd)?; + write!(key, "{:?}", ninja)?; + write!(key, "{:?}", targets)?; + write!(key, "{:?}", experimental_targets)?; + write!(key, "{:?}", link_shared)?; + write!(key, "{:?}", version_suffix)?; + write!(key, "{:?}", clang_cl)?; + write!(key, "{:?}", cflags)?; + write!(key, "{:?}", cxxflags)?; + write!(key, "{:?}", ldflags)?; + write!(key, "{:?}", use_libcxx)?; + write!(key, "{:?}", use_linker)?; + write!(key, "{:?}", allow_old_toolchain)?; + write!(key, "{:?}", offload)?; + write!(key, "{:?}", polly)?; + write!(key, "{:?}", offload_clang_dir)?; + write!(key, "{:?}", clang)?; + + match build_config { + None => { + write!(key, "None")?; + } + Some(c) => { + let mut build_config = c.iter().collect::>(); + build_config.sort(); + + for (k, v) in build_config { + write!(key, "{}: {}", k, v)?; + } + } + } + + Ok::<_, std::fmt::Error>(key) + }; + + // write! to a String always succeeds unless OOM. + helper().unwrap() + } +} + /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. /// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. #[cfg(not(test))] diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index 2c9788a0607c3..207dbed681faa 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -21,6 +21,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libzstd-dev \ && rm -rf /var/lib/apt/lists/* +# Install Intel SDE for AVX-512 emulation +RUN curl -L http://ci-mirrors.rust-lang.org/sde-external-10.8.0-2026-03-15-lin.tar.xz -o /tmp/sde.tar.xz \ + && mkdir -p /intel-sde \ + && tar -xJf /tmp/sde.tar.xz --strip-components=1 -C /intel-sde \ + && rm /tmp/sde.tar.xz + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -29,4 +35,5 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ --enable-profiler \ --enable-compiler-docs \ --set llvm.libzstd=true" -ENV SCRIPT="python3 ../x.py --stage 2 test" +ENV SCRIPT="python3 ../x.py --stage 2 test && \ + python3 ../x.py --stage 2 test library/stdarch/crates/intrinsic-test" \ No newline at end of file diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 00794371d50c6..ccc524c577dd4 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -80,15 +80,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "2.11.1" @@ -262,6 +253,15 @@ dependencies = [ "cc", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "codespan-reporting" version = "0.13.1" @@ -460,6 +460,18 @@ dependencies = [ "syn", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -504,12 +516,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -805,18 +811,19 @@ dependencies = [ [[package]] name = "ipc-channel" -version = "0.20.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180" +checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61" dependencies = [ - "bincode", "crossbeam-channel", - "fnv", "libc", "mio", + "postcard", "rand 0.9.4", - "serde", + "rustc-hash 2.1.2", + "serde_core", "tempfile", + "thiserror 2.0.18", "uuid", "windows", ] @@ -982,7 +989,7 @@ dependencies = [ "memmap2", "parking_lot", "perf-event-open-sys", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", ] @@ -1192,6 +1199,18 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -1366,6 +1385,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc_version" version = "0.4.1" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 7d7770eddcbe8..a08e9210028d6 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -38,7 +38,7 @@ serde = { version = "1.0.219", features = ["derive"], optional = true } [target.'cfg(target_os = "linux")'.dependencies] nix = { version = "0.30.1", features = ["mman", "ptrace", "signal"], optional = true } -ipc-channel = { version = "0.20.0", optional = true } +ipc-channel = { version = "0.22.0", optional = true } capstone = { version = "0.14", features = ["arch_x86", "full"], default-features = false, optional = true} [target.'cfg(all(target_os = "linux", target_pointer_width = "64", target_endian = "little"))'.dependencies] diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 8a4d09b8348bf..f58cec827cf5d 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -342,7 +342,7 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); let target_crate = is_target_crate(); - let store_json = |info: CrateRunInfo| { + let store_json = |info: &CrateRunInfo| { if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") { // Create a stub .d file to stop Cargo from "rebuilding" the crate: // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693 @@ -383,9 +383,9 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { // like we want them. // Instead of compiling, we write JSON into the output file with all the relevant command-line flags // and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase. - let env = CrateRunEnv::collect(args, inside_rustdoc); + let info = CrateRunInfo::collect(args, inside_rustdoc); - store_json(CrateRunInfo::RunWith(env.clone())); + store_json(&info); // Rustdoc expects us to exit with an error code if the test is marked as `compile_fail`, // just creating the JSON file is not enough: we need to detect syntax errors, @@ -395,7 +395,8 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { // Ensure --emit argument for a check-only build is present. if let Some(val) = - ArgFlagValueIter::from_str_iter(env.args.iter().map(|s| s as &str), "--emit").next() + ArgFlagValueIter::from_str_iter(info.args.iter().map(|s| s as &str), "--emit") + .next() { // For `no_run` tests, rustdoc passes a `--emit` flag; make sure it has the right shape. assert_eq!(val, "metadata"); @@ -405,7 +406,7 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { } // Alter the `-o` parameter so that it does not overwrite the JSON file we stored above. - let mut args = env.args; + let mut args = info.args; for i in 0..args.len() { if args[i] == "-o" { args[i + 1].push_str(".miri"); @@ -418,23 +419,22 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { if verbose > 0 { eprintln!( "[cargo-miri rustc inside rustdoc] captured input:\n{}", - std::str::from_utf8(&env.stdin).unwrap() + std::str::from_utf8(&info.stdin).unwrap() ); eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{cmd:?}"); } - exec_with_pipe(cmd, &env.stdin); + exec_with_pipe(cmd, &info.stdin); } return; } + // Unit tests for `proc-macro` crates are always built for the host so they cannot run in Miri. if runnable_crate && get_arg_flag_values("--extern").any(|krate| krate == "proc_macro") { - // This is a "runnable" `proc-macro` crate (unit tests). We do not support - // interpreting that under Miri now, so we write a JSON file to (display a - // helpful message and) skip it in the runner phase. - store_json(CrateRunInfo::SkipProcMacroTest); - return; + // Ideally we'd entirely skip them... but we have no good way of doing that here. + // So we run the tests natively on the host instead. + eprintln!("warning: unit tests of `proc-macro` crates are executed outside Miri"); } let mut cmd = miri(); @@ -537,18 +537,9 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner let file = BufReader::new(file); let binary_args = binary_args.collect::>(); - let info = serde_json::from_reader(file).unwrap_or_else(|_| { + let info: CrateRunInfo = serde_json::from_reader(file).unwrap_or_else(|_| { show_error!("file {:?} contains outdated or invalid JSON; try `cargo clean`", binary) }); - let info = match info { - CrateRunInfo::RunWith(info) => info, - CrateRunInfo::SkipProcMacroTest => { - eprintln!( - "Running unit tests of `proc-macro` crates is not currently supported by Miri." - ); - return; - } - }; let mut cmd = miri(); @@ -631,10 +622,10 @@ pub fn phase_rustdoc(args: impl Iterator) { let mut cmd = Command::new(rustdoc); cmd.args(args); - // Doctests of `proc-macro` crates (and their dependencies) are always built for the host, - // so we are not able to run them in Miri. + // Documentation tests of `proc-macro` crates are always built for the host, so we are not able + // to run them in Miri. if get_arg_flag_values("--crate-type").any(|crate_type| crate_type == "proc-macro") { - eprintln!("Running doctests of `proc-macro` crates is not currently supported by Miri."); + eprintln!("warning: doc tests of `proc-macro` crates are not supported by Miri"); return; } diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index 1952435c59977..6d19830e71d44 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -22,9 +22,9 @@ macro_rules! show_error { } pub(crate) use show_error; -/// The information to run a crate with the given environment. -#[derive(Clone, Serialize, Deserialize)] -pub struct CrateRunEnv { +/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled". +#[derive(Serialize, Deserialize)] +pub struct CrateRunInfo { /// The command-line arguments. pub args: Vec, /// The environment. @@ -35,7 +35,7 @@ pub struct CrateRunEnv { pub stdin: Vec, } -impl CrateRunEnv { +impl CrateRunInfo { /// Gather all the information we need. pub fn collect(args: impl Iterator, capture_stdin: bool) -> Self { let args = args.collect(); @@ -47,20 +47,9 @@ impl CrateRunEnv { std::io::stdin().lock().read_to_end(&mut stdin).expect("cannot read stdin"); } - CrateRunEnv { args, env, current_dir, stdin } + CrateRunInfo { args, env, current_dir, stdin } } -} -/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled". -#[derive(Serialize, Deserialize)] -pub enum CrateRunInfo { - /// Run it with the given environment. - RunWith(CrateRunEnv), - /// Skip it as Miri does not support interpreting such kind of crates. - SkipProcMacroTest, -} - -impl CrateRunInfo { pub fn store(&self, filename: &Path) { let file = File::create(filename) .unwrap_or_else(|_| show_error!("cannot create `{}`", filename.display())); diff --git a/src/tools/miri/priroda/Cargo.lock b/src/tools/miri/priroda/Cargo.lock index 2eb63f8a16b3b..7d46f75d2fab7 100644 --- a/src/tools/miri/priroda/Cargo.lock +++ b/src/tools/miri/priroda/Cargo.lock @@ -80,15 +80,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "2.11.1" @@ -225,6 +216,15 @@ dependencies = [ "inout", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "color-eyre" version = "0.6.5" @@ -339,6 +339,18 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -383,12 +395,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -540,18 +546,19 @@ dependencies = [ [[package]] name = "ipc-channel" -version = "0.20.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180" +checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61" dependencies = [ - "bincode", "crossbeam-channel", - "fnv", "libc", "mio", + "postcard", "rand 0.9.4", - "serde", + "rustc-hash 2.1.2", + "serde_core", "tempfile", + "thiserror 2.0.18", "uuid", "windows", ] @@ -667,7 +674,7 @@ dependencies = [ "memmap2", "parking_lot", "perf-event-open-sys", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", ] @@ -840,6 +847,18 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1014,6 +1033,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc_version" version = "0.4.1" diff --git a/src/tools/miri/priroda/README.md b/src/tools/miri/priroda/README.md index e0dafd2685504..b9d946e08e544 100644 --- a/src/tools/miri/priroda/README.md +++ b/src/tools/miri/priroda/README.md @@ -8,6 +8,7 @@ Current focus: - single-threaded stepping with Miri's interpreter - source-location output after stepping - source-location breakpoint prototype +- source-local listing prototype ## Setup @@ -59,9 +60,11 @@ RUSTC_BLESS=1 cargo test | Command | Description | |---|---| -| Enter, `s`, `step` | Execute one Miri interpreter step. | +| Enter, `si`, `stepi` | Execute one Miri interpreter step. | +| `s`, `step` | Step until the displayed source location changes. | | `c`, `continue` | Continue until the program finishes or reaches a breakpoint. | | `b :`, `break :` | Add a source-location breakpoint. | +| `l`, `locals` | List source-level locals in the current frame by name. | | `q`, `quit` | Exit Priroda. | EOF also exits Priroda cleanly. diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs index 6ac0ce761dcb0..2739b041b0b48 100644 --- a/src/tools/miri/priroda/src/main.rs +++ b/src/tools/miri/priroda/src/main.rs @@ -71,7 +71,7 @@ impl rustc_driver::Callbacks for PrirodaCompilerCalls { let ecx = create_ecx(tcx); let mut session = PrirodaContext::new(ecx); - let cli = CLI {}; + let cli = Cli {}; let result = cli.run_cli_loop(&mut session); match result.report_err() { @@ -133,6 +133,10 @@ struct PrirodaContext<'tcx> { enum ResumeMode { /// Stop at the next visible MIR instruction. MirInstruction, + /// Stop at the next source line + /// + /// Take `Option` because some cases current state has no mapped to source code location + SourceLine(Option<(PathBuf, usize)>), /// Continue until reaching a breakpoint. Continue, } @@ -159,10 +163,31 @@ impl<'tcx> PrirodaContext<'tcx> { Self { ecx, breakpoints: HashMap::new(), current_location: None, last_location: None } } + fn local_path(&self, location: &SourceLocation) -> Option { + let source_map = self.ecx.tcx.sess.source_map(); + location.local_path(source_map) + } + + fn current_source_position(&self) -> Option<(PathBuf, usize)> { + let location = self.current_location.as_ref()?; + Some((self.local_path(location)?, location.line)) + } + + // Used to treat `continue` like a source-level step for breakpoint checks: + // several MIR locations can point at one source line, but they should only + // report that source breakpoint once. + fn last_source_position(&self) -> Option<(PathBuf, usize)> { + let location = self.last_location.as_ref()?; + Some((self.local_path(location)?, location.line)) + } + /// Step to the next visible MIR instruction. - fn step(&mut self) -> InterpResult<'tcx, StepResult> { + fn stepi(&mut self) -> InterpResult<'tcx, StepResult> { self.resume(ResumeMode::MirInstruction) } + fn step(&mut self) -> InterpResult<'tcx, StepResult> { + self.resume(ResumeMode::SourceLine(self.current_source_position())) + } /// Continue execution until reaching a breakpoint or propagating termination. fn continue_execution(&mut self) -> InterpResult<'tcx, StepResult> { @@ -202,6 +227,26 @@ impl<'tcx> PrirodaContext<'tcx> { { return interp_ok(StepResult::Step); } + + ResumeMode::SourceLine(ref prev_location) => { + match (prev_location, &self.current_location) { + // We started from an unmapped source location. Stop at the first mapped source location we can show to the user. + (None, Some(_)) => return interp_ok(StepResult::Step), + + (Some((prev_path, prev_line)), Some(current_location)) => { + if let Some(current_path) = self.local_path(current_location) { + // A source step stops when the visible source position changes to a different file or line. + if *prev_path != current_path || *prev_line != current_location.line + { + return interp_ok(StepResult::Step); + } + } + } + + _ => {} + } + } + ResumeMode::MirInstruction | ResumeMode::Continue => {} } } @@ -248,21 +293,20 @@ impl<'tcx> PrirodaContext<'tcx> { } fn is_at_breakpoint(&self) -> bool { - // FIXME: avoid repeated stops when one source line maps to multiple MIR statements. - let Some(location) = &self.current_location else { + let Some(bp) = self.current_breakpoint() else { return false; }; - let source_map = self.ecx.tcx.sess.source_map(); - let Some(path) = &location.local_path(source_map) else { - return false; - }; + // If the previous interpreter step had the same source position, this + // is another MIR location for the breakpoint we just reported. + self.last_source_position().as_ref() != Some(&bp) + } - let lines = match self.breakpoints.get(path) { - Some(lines) => lines, - None => return false, - }; - lines.contains(&location.line) + fn current_breakpoint(&self) -> Option<(PathBuf, usize)> { + let (path, line) = self.current_source_position()?; + let lines = self.breakpoints.get(&path)?; + + if lines.contains(&line) { Some((path, line)) } else { None } } fn resolve_current_location(&self) -> Option { @@ -276,26 +320,41 @@ impl<'tcx> PrirodaContext<'tcx> { let source_map = self.ecx.tcx.sess.source_map(); let loc = source_map.lookup_char_pos(span.lo()); - Some(SourceLocation { span: span, line: loc.line }) + Some(SourceLocation { span, line: loc.line }) } fn run_command(&mut self, command: DebuggerCommand) -> InterpResult<'tcx, CommandResult> { match command { + DebuggerCommand::StepI => self.stepi().map(CommandResult::ExecutionStopped), DebuggerCommand::Step => self.step().map(CommandResult::ExecutionStopped), DebuggerCommand::Continue => self.continue_execution().map(CommandResult::ExecutionStopped), DebuggerCommand::Breakpoint(path, line) => interp_ok(CommandResult::BreakpointResult(self.set_breakpoint(path, line))), + DebuggerCommand::ListLocals => interp_ok(CommandResult::Locals(self.list_locals())), DebuggerCommand::TerminateSession => interp_ok(CommandResult::TerminateSession), } } + + /// Returns the names of all user-visible locals in the innermost stack frame. + /// + /// Uses `var_debug_info` from the MIR body, which is the same source that + /// DWARF debug info is built from, so the names match what the user wrote. + fn list_locals(&self) -> Vec { + let Some(frame) = self.ecx.active_thread_stack().last() else { + return Vec::new(); + }; + frame.body().var_debug_info.iter().map(|info| info.name.to_string()).collect() + } } enum DebuggerCommand { + StepI, Step, TerminateSession, Continue, Breakpoint(PathBuf, usize), + ListLocals, } enum BreakpointSetResult { @@ -307,14 +366,15 @@ enum BreakpointSetResult { enum CommandResult { ExecutionStopped(StepResult), BreakpointResult(BreakpointSetResult), + Locals(Vec), // FIXME: distinguish terminating the debugger session from disconnecting a // frontend and terminating the interpreted program once multiple frontends exist. TerminateSession, } -struct CLI; +struct Cli; -impl CLI { +impl Cli { pub fn run_cli_loop<'tcx>(&self, session: &mut PrirodaContext<'tcx>) -> InterpResult<'tcx> { loop { print!("(priroda) "); @@ -334,7 +394,7 @@ impl CLI { if matches!(result, StepResult::Breakpoint) { println!("Hit breakpoint"); } - self.print_location(&session); + self.print_location(session); } CommandResult::BreakpointResult(res) => match res { @@ -343,6 +403,14 @@ impl CLI { BreakpointSetResult::Duplicate => println!("Duplicate breakpoint"), }, + CommandResult::Locals(names) => + if names.is_empty() { + println!("no locals"); + } else { + for name in &names { + println!("{name}"); + } + }, CommandResult::TerminateSession => { println!("quitting"); return interp_ok(()); @@ -367,21 +435,24 @@ impl CLI { let args = parts.next().unwrap_or("").trim(); match command { - "" | "s" | "step" => Some(DebuggerCommand::Step), + // FIXME: empty line should repats last command user typed not exeute specific command. + "" | "si" | "stepi" => Some(DebuggerCommand::StepI), + "s" | "step" => Some(DebuggerCommand::Step), "q" | "quit" => Some(DebuggerCommand::TerminateSession), "c" | "continue" => Some(DebuggerCommand::Continue), "b" | "break" => self.parse_breakpoint(args), + "l" | "locals" => Some(DebuggerCommand::ListLocals), _ => None, } } fn print_location(&self, session: &PrirodaContext) { - let source_map = session.ecx.tcx.sess.source_map(); match &session.current_location { Some(location) => - if let Some(path) = location.local_path(source_map) { + if let Some(path) = session.local_path(location) { println!("{}:{}", path.display(), location.line); } else { + let source_map = session.ecx.tcx.sess.source_map(); println!("{}", source_map.span_to_diagnostic_string(location.span)); }, None => println!("no-location"), diff --git a/src/tools/miri/priroda/tests/ui/locals_in_function.rs b/src/tools/miri/priroda/tests/ui/locals_in_function.rs new file mode 100644 index 0000000000000..755b649f42299 --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_in_function.rs @@ -0,0 +1,7 @@ +// Verifies that the `locals` command lists the names of user-declared variables +// in the current stack frame. After stepping into `main` we should see `x` and `y`. +fn main() { + let x = 1_i32; + let y = true; + let _ = (x, y); +} diff --git a/src/tools/miri/priroda/tests/ui/locals_in_function.stdin b/src/tools/miri/priroda/tests/ui/locals_in_function.stdin new file mode 100644 index 0000000000000..31bbdb051a6e8 --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_in_function.stdin @@ -0,0 +1,4 @@ +break tests/ui/locals_in_function.rs:5 +continue +locals +quit diff --git a/src/tools/miri/priroda/tests/ui/locals_in_function.stdout b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout new file mode 100644 index 0000000000000..ed5889f5836e7 --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout @@ -0,0 +1,6 @@ +(priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 +(priroda) Hit breakpoint +{MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 +(priroda) x +y +(priroda) quitting diff --git a/src/tools/miri/priroda/tests/ui/locals_no_frame.rs b/src/tools/miri/priroda/tests/ui/locals_no_frame.rs new file mode 100644 index 0000000000000..c868045ddaa9f --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_no_frame.rs @@ -0,0 +1,4 @@ +// Verifies that the `locals` command reports "no locals" when invoked before +// any user stack frame is active (i.e. immediately at startup, while the std +// runtime preamble is running). +fn main() {} diff --git a/src/tools/miri/priroda/tests/ui/locals_no_frame.stdin b/src/tools/miri/priroda/tests/ui/locals_no_frame.stdin new file mode 100644 index 0000000000000..380b346c27d9e --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_no_frame.stdin @@ -0,0 +1,2 @@ +locals +quit diff --git a/src/tools/miri/priroda/tests/ui/locals_no_frame.stdout b/src/tools/miri/priroda/tests/ui/locals_no_frame.stdout new file mode 100644 index 0000000000000..3a4c983f0bb60 --- /dev/null +++ b/src/tools/miri/priroda/tests/ui/locals_no_frame.stdout @@ -0,0 +1,2 @@ +(priroda) no locals +(priroda) quitting diff --git a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.rs b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.rs index 4a1247ab37b4a..494e7f209699b 100644 --- a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.rs +++ b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.rs @@ -1,7 +1,8 @@ -// Documents the current repeated-stop behavior when multiple MIR locations map -// to the same source breakpoint line. -// This may look trivial, but a bunch of code runs in std before -// `main` is called, so we are ensuring that that all works. +// Verifies duplicate MIR locations on one source breakpoint line are skipped. +// The following line gives the second `continue` a later real breakpoint. +// This keeps the test from passing merely because the program finished. +// Keep the breakpoint line numbers in the .stdin file in sync with this file. fn main() { - let _value = 0; + let _first = 0; + let _second = 1; } diff --git a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdin b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdin index a179d469cc2ba..aaaf7479f641a 100644 --- a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdin +++ b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdin @@ -1,4 +1,5 @@ break tests/ui/repeated_same_line_breakpoint.rs:6 +break tests/ui/repeated_same_line_breakpoint.rs:7 continue continue quit diff --git a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdout b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdout index 27ba93d504ed4..1ab080cbfa9b1 100644 --- a/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdout +++ b/src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdout @@ -1,6 +1,7 @@ (priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6 +(priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:7 (priroda) Hit breakpoint {MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6 (priroda) Hit breakpoint -{MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6 +{MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:7 (priroda) quitting diff --git a/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdin b/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdin index 955048258c669..dd255f4abf43e 100644 --- a/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdin +++ b/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdin @@ -1,3 +1,3 @@ +si s -step quit diff --git a/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdout b/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdout index bd2d2487d316b..10cc3a5cf980b 100644 --- a/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdout +++ b/src/tools/miri/priroda/tests/ui/source_step_changes_line.stdout @@ -1,3 +1,3 @@ (priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:206 -(priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:206 +(priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:207 (priroda) quitting diff --git a/src/tools/miri/priroda/tests/ui/step_aliases.stdin b/src/tools/miri/priroda/tests/ui/step_aliases.stdin index 923b000e78e7e..0ad1ca7ec1038 100644 --- a/src/tools/miri/priroda/tests/ui/step_aliases.stdin +++ b/src/tools/miri/priroda/tests/ui/step_aliases.stdin @@ -1,4 +1,4 @@ -s -step +si +stepi quit diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 387bd8edd2196..4a2bfdb2cd558 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -029c9e18dd1f4668e1d42bb187c1c263dfe20093 +01f54e80e888b66d6486a3a95d481b87353016df diff --git a/src/tools/miri/src/shims/native_lib/trace/child.rs b/src/tools/miri/src/shims/native_lib/trace/child.rs index d7d9a591911a0..406c2916eb13e 100644 --- a/src/tools/miri/src/shims/native_lib/trace/child.rs +++ b/src/tools/miri/src/shims/native_lib/trace/child.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::ptr::NonNull; use std::rc::Rc; -use ipc_channel::ipc; +use ipc_channel::{TryRecvError, ipc}; use nix::sys::{mman, ptrace, signal}; use nix::unistd; use rustc_const_eval::interpret::{InterpResult, interp_ok}; @@ -140,8 +140,8 @@ impl Supervisor { .try_recv_timeout(std::time::Duration::from_secs(5)) .map_err(|e| { match e { - ipc::TryRecvError::IpcError(_) => (), - ipc::TryRecvError::Empty => + TryRecvError::IpcError(_) => (), + TryRecvError::Empty => panic!("Waiting for accesses from supervisor timed out!"), } }) diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index bf1272f5bca0b..60c7e192f4805 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -172,7 +172,7 @@ def test_cargo_miri_test(): ) test("`cargo miri test` (proc-macro crate)", cargo_miri("test") + ["-p", "proc_macro_crate"], - "test.empty.ref", "test.proc-macro.stderr.ref", + "test.proc-macro.stdout.ref", "test.proc-macro.stderr.ref", ) test("`cargo miri test` (custom target dir)", cargo_miri("test") + ["--target-dir=custom-test"], diff --git a/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref b/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref index b95474208b27a..e5ff59eff3c67 100644 --- a/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref +++ b/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref @@ -1,2 +1,2 @@ -Running unit tests of `proc-macro` crates is not currently supported by Miri. -Running doctests of `proc-macro` crates is not currently supported by Miri. +warning: unit tests of `proc-macro` crates are executed outside Miri +warning: doc tests of `proc-macro` crates are not supported by Miri diff --git a/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref b/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref new file mode 100644 index 0000000000000..7326c0a25a069 --- /dev/null +++ b/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/src/tools/miri/tests/pass/both_borrows/c_variadics.rs b/src/tools/miri/tests/pass/both_borrows/c_variadics.rs index c3ec5de350bad..626022788814d 100644 --- a/src/tools/miri/tests/pass/both_borrows/c_variadics.rs +++ b/src/tools/miri/tests/pass/both_borrows/c_variadics.rs @@ -4,14 +4,13 @@ #![feature(c_variadic)] fn main() { - unsafe extern "C" fn write_with_first_arg( - ptr_to_val: *mut i32, - _hidden_mut_ref_to_val: ... - ) { + unsafe extern "C" fn write_with_first_arg(ptr_to_val: *mut i32, _hidden_mut_ref_to_val: ...) { // Retagging needs to be disabled for arguments // within the VaList. Otherwise, this write access // will be undefined behavior. - unsafe { *ptr_to_val = 32; } + unsafe { + *ptr_to_val = 32; + } } let mut val: i32 = 0; diff --git a/src/tools/miri/tests/pass/tree_borrows/slice_get_mut_no_implicit_write.rs b/src/tools/miri/tests/pass/tree_borrows/slice_get_mut_no_implicit_write.rs index 789f0a8b88ce6..4a177677cd9ac 100644 --- a/src/tools/miri/tests/pass/tree_borrows/slice_get_mut_no_implicit_write.rs +++ b/src/tools/miri/tests/pass/tree_borrows/slice_get_mut_no_implicit_write.rs @@ -24,9 +24,7 @@ fn borrowed_buf() { let ptr = unsafe { buf.as_mut() }.as_mut_ptr(); let _ = buf.capacity(); - unsafe { - ptr.write(42); - } + unsafe { ptr.write(42) }; } // A variant of the above that uses `index_mut` notation. diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 5e39dfe87004b..477ecfba2f752 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -90,7 +90,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.37.3", + "object", "rustc-demangle", "windows-link", ] @@ -1416,16 +1416,6 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libmimalloc-sys" version = "0.1.49" @@ -1589,15 +1579,6 @@ version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.9.1" @@ -1756,15 +1737,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.37.3" @@ -1992,11 +1964,7 @@ version = "0.0.0" dependencies = [ "expect-test", "intern", - "libc", - "libloading", "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap2", - "object 0.36.7", "paths", "proc-macro-test", "span", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 37e5dbb444223..3e2815e87560b 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -116,17 +116,8 @@ expect-test = "1.5.1" indexmap = { version = "2.9.0", features = ["serde"] } itertools = "0.14.0" libc = "0.2.172" -libloading = "0.8.8" -memmap2 = "0.9.5" nohash-hasher = "0.2.0" oorandom = "11.1.5" -object = { version = "0.36.7", default-features = false, features = [ - "std", - "read_core", - "elf", - "macho", - "pe", -] } postcard = { version = "1.1.3", features = ["alloc"] } process-wrap = { version = "9.1.0", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 72d394d37bfd4..f5d40a4b9ffc2 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -13,9 +13,6 @@ rust-version.workspace = true doctest = false [dependencies] -object.workspace = true -libloading.workspace = true -memmap2.workspace = true temp-dir.workspace = true paths.workspace = true @@ -24,9 +21,6 @@ span = { path = "../span", version = "0.0.0", default-features = false} intern.workspace = true -[target.'cfg(unix)'.dependencies] -libc.workspace = true - [dev-dependencies] expect-test.workspace = true line-index.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index f654d21cfe26d..1978a68dd959c 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -4,22 +4,18 @@ mod proc_macros; use rustc_codegen_ssa::back::metadata::DefaultMetadataLoader; use rustc_interface::util::rustc_version_str; -use rustc_metadata::locator::MetadataError; use rustc_proc_macro::bridge; use rustc_session::config::host_tuple; use rustc_target::spec::{Target, TargetTuple}; use std::path::Path; -use std::{fmt, fs, io, time::SystemTime}; +use std::{fs, io, time::SystemTime}; use temp_dir::TempDir; -use libloading::Library; -use object::Object; use paths::{Utf8Path, Utf8PathBuf}; use crate::{ PanicMessage, ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, TrackedEnv, - dylib::proc_macros::{ProcMacroClients, ProcMacros}, - token_stream::TokenStream, + dylib::proc_macros::ProcMacros, token_stream::TokenStream, }; pub(crate) struct Expander { @@ -28,10 +24,7 @@ pub(crate) struct Expander { } impl Expander { - pub(crate) fn new( - temp_dir: &TempDir, - lib: &Utf8Path, - ) -> Result { + pub(crate) fn new(temp_dir: &TempDir, lib: &Utf8Path) -> io::Result { // Some libraries for dynamic loading require canonicalized path even when it is // already absolute let lib = lib.canonicalize_utf8()?; @@ -78,61 +71,17 @@ impl Expander { } } -#[derive(Debug)] -pub enum LoadProcMacroDylibError { - Io(io::Error), - LibLoading(libloading::Error), - MetadataError(MetadataError<'static>), -} - -impl fmt::Display for LoadProcMacroDylibError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Io(e) => e.fmt(f), - Self::LibLoading(e) => e.fmt(f), - Self::MetadataError(e) => e.fmt(f), - } - } -} - -impl From for LoadProcMacroDylibError { - fn from(e: io::Error) -> Self { - LoadProcMacroDylibError::Io(e) - } -} - -impl From for LoadProcMacroDylibError { - fn from(e: libloading::Error) -> Self { - LoadProcMacroDylibError::LibLoading(e) - } -} - -impl From> for LoadProcMacroDylibError { - fn from(e: MetadataError<'_>) -> Self { - LoadProcMacroDylibError::MetadataError(match e { - MetadataError::NotPresent(path) => MetadataError::NotPresent(path.into_owned().into()), - MetadataError::LoadFailure(err) => MetadataError::LoadFailure(err), - MetadataError::VersionMismatch { expected_version, found_version } => { - MetadataError::VersionMismatch { expected_version, found_version } - } - }) - } -} - struct ProcMacroLibrary { - // this contains references to the library, so make sure this drops before _lib proc_macros: ProcMacros, - // Hold on to the library so it doesn't unload - _lib: Library, } impl ProcMacroLibrary { - fn open(path: &Utf8Path) -> Result { - let proc_macro_kinds = rustc_span::create_default_session_globals_then(|| { + fn open(path: &Utf8Path) -> io::Result { + let proc_macros = rustc_span::create_default_session_globals_then(|| { let (target, _) = Target::search(&TargetTuple::from_tuple(host_tuple()), Path::new(""), false) .unwrap(); - rustc_metadata::locator::get_proc_macro_info( + rustc_metadata::locator::get_proc_macros( &target, path.as_ref(), &DefaultMetadataLoader, @@ -140,63 +89,10 @@ impl ProcMacroLibrary { ) })?; - let file = fs::File::open(path)?; - #[allow(clippy::undocumented_unsafe_blocks)] // FIXME - let file = unsafe { memmap2::Mmap::map(&file) }?; - let obj = object::File::parse(&*file) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - let symbol_name = - find_registrar_symbol(&obj).map_err(invalid_data_err)?.ok_or_else(|| { - invalid_data_err(format!("Cannot find registrar symbol in file {path}")) - })?; - - // SAFETY: We have verified the validity of the dylib as a proc-macro library - let lib = unsafe { load_library(path) }.map_err(invalid_data_err)?; - // SAFETY: We have verified the validity of the dylib as a proc-macro library - // The 'static lifetime is a lie, it's actually the lifetime of the library but unavoidable - // due to self-referentiality - // But we make sure that we do not drop it before the symbol is dropped - let proc_macros = - unsafe { lib.get::<&'static &'static ProcMacroClients>(symbol_name.as_bytes()) }; - match proc_macros { - Ok(proc_macros) => Ok(ProcMacroLibrary { - proc_macros: ProcMacros::new(*proc_macros, proc_macro_kinds), - _lib: lib, - }), - Err(e) => Err(e.into()), - } + Ok(ProcMacroLibrary { proc_macros: ProcMacros::new(proc_macros) }) } } -fn invalid_data_err(e: impl Into>) -> io::Error { - io::Error::new(io::ErrorKind::InvalidData, e) -} - -fn is_derive_registrar_symbol(symbol: &str) -> bool { - const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; - symbol.contains(NEW_REGISTRAR_SYMBOL) -} - -fn find_registrar_symbol(obj: &object::File<'_>) -> object::Result> { - Ok(obj - .exports()? - .into_iter() - .map(|export| export.name()) - .filter_map(|sym| String::from_utf8(sym.into()).ok()) - .find(|sym| is_derive_registrar_symbol(sym)) - .map(|sym| { - // From MacOS docs: - // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html - // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be - // prepended with an underscore. - if cfg!(target_os = "macos") && sym.starts_with('_') { - sym[1..].to_owned() - } else { - sym - } - })) -} - /// Copy the dylib to temp directory to prevent locking in Windows #[cfg(windows)] fn ensure_file_with_lock_free_access( @@ -233,54 +129,3 @@ fn ensure_file_with_lock_free_access( ) -> io::Result { Ok(path.to_owned()) } - -/// Loads dynamic library in platform dependent manner. -/// -/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described -/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample) -/// and [here](https://github.com/rust-lang/rust/issues/60593). -/// -/// Usage of RTLD_DEEPBIND -/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1) -/// -/// It seems that on Windows that behaviour is default, so we do nothing in that case. -/// -/// # Safety -/// -/// The caller is responsible for ensuring that the path is valid proc-macro library -#[cfg(windows)] -unsafe fn load_library(file: &Utf8Path) -> Result { - // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library - unsafe { Library::new(file) } -} - -/// Loads dynamic library in platform dependent manner. -/// -/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described -/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample) -/// and [here](https://github.com/rust-lang/rust/issues/60593). -/// -/// Usage of RTLD_DEEPBIND -/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1) -/// -/// It seems that on Windows that behaviour is default, so we do nothing in that case. -/// -/// # Safety -/// -/// The caller is responsible for ensuring that the path is valid proc-macro library -#[cfg(unix)] -unsafe fn load_library(file: &Utf8Path) -> Result { - // not defined by POSIX, different values on mips vs other targets - #[cfg(target_env = "gnu")] - use libc::RTLD_DEEPBIND; - use libloading::os::unix::Library as UnixLibrary; - // defined by POSIX - use libloading::os::unix::RTLD_NOW; - - // MUSL and bionic don't have it.. - #[cfg(not(target_env = "gnu"))] - const RTLD_DEEPBIND: std::os::raw::c_int = 0x0; - - // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library - unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) } -} diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs index ef6752d81698d..4976298d5fcd1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs @@ -4,9 +4,6 @@ use crate::{ }; use rustc_proc_macro::bridge; -#[repr(transparent)] -pub(crate) struct ProcMacroClients([bridge::client::Client]); - impl From for crate::PanicMessage { fn from(p: bridge::PanicMessage) -> Self { Self { message: p.into_string() } @@ -17,10 +14,9 @@ pub(crate) struct ProcMacros(Vec<(bridge::client::Client, rustc_metadata::ProcMa impl ProcMacros { pub(super) fn new( - clients: &ProcMacroClients, - kinds: Vec, + macros: Vec<(bridge::client::Client, rustc_metadata::ProcMacroKind)>, ) -> Self { - ProcMacros(clients.0.iter().copied().zip(kinds).collect::>()) + ProcMacros(macros) } pub(crate) fn expand<'a, S: ProcMacroSrvSpan>( diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index b8cd3621d698f..2a3a1bc002601 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -10,9 +10,10 @@ #![cfg(feature = "in-rust-tree")] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] -#![expect(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)] +#![expect(internal_features, clippy::disallowed_types, clippy::print_stderr)] #![allow(unused_features, unused_crate_dependencies)] #![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)] +#![cfg_attr(test, expect(unreachable_pub))] extern crate rustc_codegen_ssa; extern crate rustc_driver as _; diff --git a/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff new file mode 100644 index 0000000000000..e59e2fde016d2 --- /dev/null +++ b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff @@ -0,0 +1,27 @@ +- // MIR for `dont_remove_moved_comparison` before SimplifyComparisonIntegral ++ // MIR for `dont_remove_moved_comparison` after SimplifyComparisonIntegral + + fn dont_remove_moved_comparison(_1: i8) -> i32 { + let mut _0: i32; + let mut _2: bool; + let mut _3: i32; + let mut _4: i32; + + bb0: { + _2 = Eq(copy _1, const 17_i8); + _3 = copy _2 as i32 (IntToInt); +- switchInt(move _2) -> [1: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [17: bb1, otherwise: bb2]; + } + + bb1: { + _0 = copy _3; + return; + } + + bb2: { + _0 = Add(copy _3, const 1_i32); + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff index 22f6443a6c0f9..58c95e20975ee 100644 --- a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 'x'); + _2 = Eq(copy _1, const 'x'); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [120: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff index d5c48fd04ca60..23dc079de01a0 100644 --- a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_i8); + _2 = Eq(copy _1, const 42_i8); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff index 84d62b8136078..5baf481616186 100644 --- a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff @@ -13,9 +13,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_u32); + _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } @@ -30,9 +29,8 @@ StorageLive(_4); StorageLive(_5); _5 = copy _1; -- _4 = Ne(copy _1, const 21_u32); + _4 = Ne(copy _1, const 21_u32); - switchInt(move _4) -> [0: bb4, otherwise: bb3]; -+ nop; + switchInt(copy _1) -> [21: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff index a1cbaff796b35..79c3525663c89 100644 --- a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const -42_i32); + _2 = Eq(copy _1, const -42_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [4294967254: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff index 8101de8cbf381..3e950f053bc35 100644 --- a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_u32); + _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.rs b/tests/mir-opt/if_condition_int.rs index 5e0961da3ccea..6eed1191ffc57 100644 --- a/tests/mir-opt/if_condition_int.rs +++ b/tests/mir-opt/if_condition_int.rs @@ -85,7 +85,7 @@ fn opt_multiple_ifs(x: u32) -> u32 { } // EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff -// test that we optimize, but do not remove the b statement, as that is used later on +// the switchInt can be optimized but the b statement can't be removed as it's used later on fn dont_remove_comparison(a: i8) -> i32 { // CHECK-LABEL: fn dont_remove_comparison( // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8); @@ -103,6 +103,42 @@ fn dont_remove_comparison(a: i8) -> i32 { } } +// EMIT_MIR if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff +// like dont_remove_comparison above, but with switchInt(move _N) - regression test for #158206 +#[custom_mir(dialect = "runtime")] +fn dont_remove_moved_comparison(a: i8) -> i32 { + // CHECK-LABEL: fn dont_remove_moved_comparison( + // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8); + // CHECK: [[cast:_.*]] = copy [[b]] as i32 (IntToInt); + // CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = copy [[cast]]; + // CHECK: [[BB2]]: + // CHECK: _0 = Add(copy [[cast]], const 1_i32); + mir! { + let b: bool; + let c: i32; + let d: i32; + { + b = a == 17; + c = b as i32; + match Move(b) { + true => bb1, + _ => bb2, + } + + } + bb1 = { + RET = c; + Return() + } + bb2 = { + RET = c + 1; + Return() + } + } +} + // EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff // test that we do not optimize on floats fn dont_opt_floats(a: f32) -> i32 { diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr index b43a67a656127..4a131b9c2a2a6 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr @@ -1,85 +1,75 @@ -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on constants --> $DIR/incorrect-locations.rs:7:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const CONST: () = (); - | --------------------- not a trait implementation | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on statics --> $DIR/incorrect-locations.rs:11:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | static STATIC: () = (); - | ----------------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on type aliases --> $DIR/incorrect-locations.rs:15:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Type = (); - | --------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on enums --> $DIR/incorrect-locations.rs:19:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | enum Enum {} - | ------------ not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on inherent impl blocks --> $DIR/incorrect-locations.rs:23:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Enum {} - | ------------ not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on foreign modules --> $DIR/incorrect-locations.rs:27:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern "C" {} - | ------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on functions --> $DIR/incorrect-locations.rs:31:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn fun() {} - | ----------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on structs --> $DIR/incorrect-locations.rs:35:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Struct {} - | ---------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on traits --> $DIR/incorrect-locations.rs:39:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | trait Trait {} - | -------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks warning: 9 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr index b43a67a656127..4a131b9c2a2a6 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr @@ -1,85 +1,75 @@ -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on constants --> $DIR/incorrect-locations.rs:7:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const CONST: () = (); - | --------------------- not a trait implementation | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on statics --> $DIR/incorrect-locations.rs:11:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | static STATIC: () = (); - | ----------------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on type aliases --> $DIR/incorrect-locations.rs:15:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Type = (); - | --------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on enums --> $DIR/incorrect-locations.rs:19:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | enum Enum {} - | ------------ not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on inherent impl blocks --> $DIR/incorrect-locations.rs:23:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Enum {} - | ------------ not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on foreign modules --> $DIR/incorrect-locations.rs:27:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern "C" {} - | ------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on functions --> $DIR/incorrect-locations.rs:31:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn fun() {} - | ----------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on structs --> $DIR/incorrect-locations.rs:35:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Struct {} - | ---------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks -warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations +warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on traits --> $DIR/incorrect-locations.rs:39:1 | LL | #[diagnostic::do_not_recommend] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | trait Trait {} - | -------------- not a trait implementation + | + = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks warning: 9 warnings emitted diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs index e716457eaedf4..fc1ba5863b2d3 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs @@ -5,39 +5,39 @@ //@ reference: attributes.diagnostic.do_not_recommend.allowed-positions #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on const CONST: () = (); #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on static STATIC: () = (); #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on type Type = (); #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on enum Enum {} #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on impl Enum {} #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on extern "C" {} #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on fn fun() {} #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on struct Struct {} #[diagnostic::do_not_recommend] -//~^WARN `#[diagnostic::do_not_recommend]` can only be placed +//~^WARN cannot be used on trait Trait {} #[diagnostic::do_not_recommend] diff --git a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs index 940d4623cba86..21b7dc32f6f8e 100644 --- a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs +++ b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs @@ -2,7 +2,7 @@ #![deny(misplaced_diagnostic_attributes)] #[diagnostic::on_const(message = "tadaa", note = "boing")] -//~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations +//~^ ERROR: cannot be used on pub struct Foo; #[diagnostic::on_const(message = "tadaa", note = "boing")] @@ -14,7 +14,7 @@ const impl PartialEq for Foo { } #[diagnostic::on_const(message = "tadaa", note = "boing")] -//~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations +//~^ ERROR: cannot be used on impl Foo { fn eq(&self, _other: &Foo) -> bool { true @@ -23,7 +23,7 @@ impl Foo { impl PartialOrd for Foo { #[diagnostic::on_const(message = "tadaa", note = "boing")] - //~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations + //~^ ERROR: cannot be used on fn partial_cmp(&self, other: &Foo) -> Option { None } diff --git a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr index b585451cdd859..89df20ccfc668 100644 --- a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr +++ b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr @@ -13,38 +13,29 @@ note: the lint level is defined here LL | #![deny(misplaced_diagnostic_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations +error: `#[diagnostic::on_const]` attribute cannot be used on structs --> $DIR/misplaced_attr.rs:4:1 | LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | pub struct Foo; - | --------------- not a trait implementation + | + = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks -error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations +error: `#[diagnostic::on_const]` attribute cannot be used on inherent impl blocks --> $DIR/misplaced_attr.rs:16:1 | -LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / impl Foo { -LL | | fn eq(&self, _other: &Foo) -> bool { -LL | | true -LL | | } -LL | | } - | |_- not a trait implementation +LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks -error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations +error: `#[diagnostic::on_const]` attribute cannot be used on trait methods in impl blocks --> $DIR/misplaced_attr.rs:25:5 | -LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / fn partial_cmp(&self, other: &Foo) -> Option { -LL | | None -LL | | } - | |_____- not a trait implementation +LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks error: aborting due to 4 previous errors diff --git a/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.rs b/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.rs index 33e78ea5fc1fe..8de8a29be77aa 100644 --- a/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.rs +++ b/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.rs @@ -7,7 +7,7 @@ struct Foo; #[diagnostic::on_move( -//~^WARN `#[diagnostic::on_move]` can only be applied to enums, structs or unions +//~^WARN `#[diagnostic::on_move]` attribute cannot be used on traits message = "Foo", label = "Bar", )] diff --git a/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.stderr b/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.stderr index 29c987fba48f1..821feabe4de98 100644 --- a/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.stderr +++ b/tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.stderr @@ -1,4 +1,4 @@ -warning: `#[diagnostic::on_move]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_move]` attribute cannot be used on traits --> $DIR/report_warning_on_non_adt.rs:9:1 | LL | / #[diagnostic::on_move( @@ -8,6 +8,7 @@ LL | | label = "Bar", LL | | )] | |__^ | + = help: `#[diagnostic::on_move]` can only be applied to data types = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default error[E0382]: Foo diff --git a/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.rs b/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.rs index 8bcb916dac365..038862ee820a5 100644 --- a/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.rs +++ b/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.rs @@ -1,30 +1,30 @@ #![feature(diagnostic_on_type_error)] #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] -//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +//~^ WARN cannot be used on fn function() {} #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] -//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +//~^ WARN cannot be used on static STATIC: i32 = 0; #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] -//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +//~^ WARN cannot be used on mod module {} #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] -//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +//~^ WARN cannot be used on trait Trait {} #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] -//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +//~^ WARN cannot be used on type TypeAlias = i32; struct SomeStruct; impl SomeStruct { #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] - //~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions + //~^ WARN cannot be used on fn method() {} } diff --git a/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.stderr b/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.stderr index b3eafa8244a5c..a79d396397042 100644 --- a/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.stderr +++ b/tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.stderr @@ -1,40 +1,51 @@ -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on functions --> $DIR/report_warning_on_non_adt.rs:3:1 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: `#[diagnostic::on_type_error]` can only be applied to data types = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on statics --> $DIR/report_warning_on_non_adt.rs:7:1 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_type_error]` can only be applied to data types -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on modules --> $DIR/report_warning_on_non_adt.rs:11:1 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_type_error]` can only be applied to data types -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on traits --> $DIR/report_warning_on_non_adt.rs:15:1 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_type_error]` can only be applied to data types -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on type aliases --> $DIR/report_warning_on_non_adt.rs:19:1 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_type_error]` can only be applied to data types -warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions +warning: `#[diagnostic::on_type_error]` attribute cannot be used on inherent methods --> $DIR/report_warning_on_non_adt.rs:26:5 | LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[diagnostic::on_type_error]` can only be applied to data types error[E0308]: mismatched types --> $DIR/report_warning_on_non_adt.rs:38:25 diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs index aa4e14fb04f2f..03eddef2a5400 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -20,7 +20,7 @@ trait Foo {} trait Bar {} #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] -//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions +//~^WARN cannot be used on impl Bar for i32 {} // cannot use special rustc_on_unimplement symbols diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr index 7ab7f25ee6964..4059bcaec7573 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -152,12 +152,13 @@ LL | #[diagnostic::on_unimplemented = "Message"] | = help: only `message`, `note` and `label` are allowed as options -warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions +warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on trait impl blocks --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1 | LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: `#[diagnostic::on_unimplemented]` can only be applied to traits = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: format specifiers are not permitted in diagnostic attributes diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 14763d21a2bea..dd78f7f5a9f35 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -5,7 +5,7 @@ trait Foo {} #[diagnostic::on_unimplemented(message = "Baz")] -//~^WARN `#[diagnostic::on_unimplemented]` can only be applied to trait definitions +//~^WARN cannot be used on struct Bar {} #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index d5c7f25efbc29..739bd598e9c69 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -16,12 +16,13 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = help: only `message`, `note` and `label` are allowed as options = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions +warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on structs --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:7:1 | LL | #[diagnostic::on_unimplemented(message = "Baz")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: `#[diagnostic::on_unimplemented]` can only be applied to traits = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: malformed `diagnostic::on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.rs index 1ffa604b2bc06..658cc53246c13 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.rs @@ -6,7 +6,7 @@ trait Test {} #[diagnostic::on_unimplemented(message = "blah", label = "blah", note = "blah")] -//~^ WARN `#[diagnostic::on_unimplemented]` can only be applied to trait definitions +//~^ WARN cannot be used on trait Alias = Test; // Use trait alias as bound on type parameter. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.stderr index e9d0c6e5daf55..a9a38da242268 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.stderr @@ -1,9 +1,10 @@ -warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions +warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on trait aliases --> $DIR/on_impl_trait.rs:8:1 | LL | #[diagnostic::on_unimplemented(message = "blah", label = "blah", note = "blah")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: `#[diagnostic::on_unimplemented]` can only be applied to traits = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default error[E0277]: the trait bound `{integer}: Alias` is not satisfied diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.rs b/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.rs index ec32bf5ba54f7..f82e52f2f6a3e 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.rs +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.rs @@ -3,47 +3,47 @@ #![feature(diagnostic_on_unknown)] #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on extern crate std as other_std; #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on const CONST: () = (); #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on static STATIC: () = (); #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on type Type = (); #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on enum Enum {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on impl Enum {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on extern "C" {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on fn fun() {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on struct Struct {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on trait Trait {} #[diagnostic::on_unknown(message = "foo")] -//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +//~^WARN cannot be used on impl Trait for i32 {} #[diagnostic::on_unknown(message = "foo")] diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.stderr b/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.stderr index c812e99260660..81508568d0e0e 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.stderr +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.stderr @@ -1,103 +1,91 @@ -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on extern crates --> $DIR/incorrect_locations.rs:5:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern crate std as other_std; - | ------------------------------ not an import or module | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on constants --> $DIR/incorrect_locations.rs:9:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const CONST: () = (); - | --------------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on statics --> $DIR/incorrect_locations.rs:13:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | static STATIC: () = (); - | ----------------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on type aliases --> $DIR/incorrect_locations.rs:17:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Type = (); - | --------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on enums --> $DIR/incorrect_locations.rs:21:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | enum Enum {} - | ------------ not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on inherent impl blocks --> $DIR/incorrect_locations.rs:25:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Enum {} - | ------------ not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on foreign modules --> $DIR/incorrect_locations.rs:29:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern "C" {} - | ------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on functions --> $DIR/incorrect_locations.rs:33:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn fun() {} - | ----------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on structs --> $DIR/incorrect_locations.rs:37:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Struct {} - | ---------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on traits --> $DIR/incorrect_locations.rs:41:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | trait Trait {} - | -------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on trait impl blocks --> $DIR/incorrect_locations.rs:45:1 | LL | #[diagnostic::on_unknown(message = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Trait for i32 {} - | --------------------- not an import or module + | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements warning: 11 warnings emitted diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.rs b/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.rs index 7795d346f22b3..0191c66dd7e80 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.rs +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.rs @@ -6,6 +6,6 @@ fn main() { #[diagnostic::on_unknown(message = "anonymous block")] - //~^ WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations + //~^ WARN cannot be used on {} } diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.stderr b/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.stderr index daa6688abf2d5..dc02dc4272487 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.stderr +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.stderr @@ -1,12 +1,10 @@ -warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations +warning: `#[diagnostic::on_unknown]` attribute cannot be used on expressions --> $DIR/incorrect_unstable_positions.rs:8:5 | LL | #[diagnostic::on_unknown(message = "anonymous block")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | {} - | -- not an import or module | + = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: 1 warning emitted diff --git a/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.rs b/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.rs index 28b6e0cbe3be7..537e7c292c99a 100644 --- a/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.rs +++ b/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.rs @@ -2,7 +2,7 @@ #![feature(diagnostic_on_unmatched_args)] #[diagnostic::on_unmatched_args(message = "not allowed here")] -//~^ WARN `#[diagnostic::on_unmatched_args]` can only be applied to macro definitions +//~^ WARN cannot be used on struct Foo; fn main() { diff --git a/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.stderr b/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.stderr index 10c6fd9ce8bea..bd94410ff72f7 100644 --- a/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.stderr +++ b/tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.stderr @@ -1,9 +1,10 @@ -warning: `#[diagnostic::on_unmatched_args]` can only be applied to macro definitions +warning: `#[diagnostic::on_unmatched_args]` attribute cannot be used on structs --> $DIR/report_warning_on_non_macro.rs:4:1 | LL | #[diagnostic::on_unmatched_args(message = "not allowed here")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: `#[diagnostic::on_unmatched_args]` can only be applied to macro defs = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: 1 warning emitted diff --git a/triagebot.toml b/triagebot.toml index d19e262dfd099..411796a853216 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1531,6 +1531,7 @@ libs = [ "@clarfonthey", "@aapoalas", "@Darksonn", + "@JohnTitor", ] infra-ci = [ "@Mark-Simulacrum", @@ -1560,7 +1561,8 @@ diagnostics = [ "@davidtwco", "@oli-obk", "@chenyukang", - "@TaKO8Ki" + "@TaKO8Ki", + "@JohnTitor", ] parser = [ "@davidtwco",