authorbors <bors@rust-lang.org> 2026-06-21 22:59:39 UTC
committerbors <bors@rust-lang.org> 2026-06-21 22:59:39 UTC
loge238223b17937be1d3682b7f28eb91945f372ae8
tree19e9031a5f3a39ad636901771f3edc59286433de
parent91fe22da8084a1c9e993d78d4a56f22ab8396236
parent4849b10ea9dcd0f95b74e5e2aaaeaef667aa51ea

Auto merge of #158228 - JonathanBrouwer:rollup-AUgEk0s, r=JonathanBrouwer

Rollup of 9 pull requests Successful merges: - rust-lang/rust#156356 (bootstrap: add bootstrap step to run intrinsic-test in CI) - rust-lang/rust#157711 (Move proc-macro dlopen from proc-macro-srv to rustc_metadata) - rust-lang/rust#157836 (rebuild LLVM when `bootstrap.toml` config changes) - rust-lang/rust#158214 (Don't try to remove assignments in SimplifyComparisonIntegral) - rust-lang/rust#158226 (miri subtree update) - rust-lang/rust#158108 (Update actions/download-artifact action to v8.0.1) - rust-lang/rust#158150 (Update backtrace submodule to pick up AIX related fixes.) - rust-lang/rust#158178 (Use the target checking infrastructure for the diagnostic attributes) - rust-lang/rust#158195 (Add me to some rotation groups)

90 files changed, 1012 insertions(+), 891 deletions(-)

.github/workflows/dependencies.yml+2-2
......@@ -94,11 +94,11 @@ jobs:
9494 uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
9595
9696 - name: download Cargo.lock from update job
97 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
97 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
9898 with:
9999 name: Cargo-lock
100100 - name: download cargo-update log from update job
101 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
101 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
102102 with:
103103 name: cargo-updates
104104
Cargo.lock+6-14
......@@ -300,15 +300,6 @@ dependencies = [
300300 "serde",
301301]
302302
303[[package]]
304name = "bincode"
305version = "1.3.3"
306source = "registry+https://github.com/rust-lang/crates.io-index"
307checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
308dependencies = [
309 "serde",
310]
311
312303[[package]]
313304name = "bitflags"
314305version = "2.10.0"
......@@ -2106,18 +2097,19 @@ dependencies = [
21062097
21072098[[package]]
21082099name = "ipc-channel"
2109version = "0.20.2"
2100version = "0.22.0"
21102101source = "registry+https://github.com/rust-lang/crates.io-index"
2111checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180"
2102checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61"
21122103dependencies = [
2113 "bincode",
21142104 "crossbeam-channel",
2115 "fnv",
21162105 "libc",
21172106 "mio",
2107 "postcard",
21182108 "rand 0.9.2",
2119 "serde",
2109 "rustc-hash 2.1.1",
2110 "serde_core",
21202111 "tempfile",
2112 "thiserror 2.0.17",
21212113 "uuid",
21222114 "windows 0.61.3",
21232115]
compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs+5-16
......@@ -1,16 +1,14 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::Target;
33use rustc_hir::attrs::AttributeKind;
4use rustc_session::lint::builtin::{
5 MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES,
6};
4use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
75use rustc_span::{Symbol, sym};
86
7use crate::attributes::prelude::Allow;
98use crate::attributes::{OnDuplicate, SingleAttributeParser};
109use crate::context::AcceptContext;
11use crate::diagnostics::IncorrectDoNotRecommendLocation;
1210use crate::parser::ArgParser;
13use crate::target_checking::{ALL_TARGETS, AllowedTargets};
11use crate::target_checking::AllowedTargets;
1412use crate::{AttributeTemplate, template};
1513
1614pub(crate) struct DoNotRecommendParser;
......@@ -18,7 +16,8 @@ impl SingleAttributeParser for DoNotRecommendParser {
1816 const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend];
1917 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
2018 // "Allowed" on any target, noop on all but trait impls
21 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
19 const ALLOWED_TARGETS: AllowedTargets =
20 AllowedTargets::AllowListWarnRest(&[Allow(Target::Impl { of_trait: true })]);
2221 const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */);
2322 const STABILITY: AttributeStability = AttributeStability::Stable;
2423
......@@ -32,16 +31,6 @@ impl SingleAttributeParser for DoNotRecommendParser {
3231 );
3332 }
3433
35 if !matches!(cx.target, Target::Impl { of_trait: true }) {
36 let target_span = cx.target_span;
37 cx.emit_lint(
38 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
39 IncorrectDoNotRecommendLocation { target_span },
40 attr_span,
41 );
42 return None;
43 }
44
4534 Some(AttributeKind::DoNotRecommend)
4635 }
4736}
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_const.rs+5-15
......@@ -1,10 +1,8 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::attrs::diagnostic::Directive;
3use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
43
54use crate::attributes::diagnostic::*;
65use crate::attributes::prelude::*;
7use crate::diagnostics::DiagnosticOnConstOnlyForTraitImpls;
86#[derive(Default)]
97pub(crate) struct OnConstParser {
108 span: Option<Span>,
......@@ -26,18 +24,6 @@ impl AttributeParser for OnConstParser {
2624 let span = cx.attr_span;
2725 this.span = Some(span);
2826
29 // FIXME(mejrs) no constness field on `Target`,
30 // so non-constness is still checked in check_attr.rs
31 if !matches!(cx.target, Target::Impl { of_trait: true }) {
32 let target_span = cx.target_span;
33 cx.emit_lint(
34 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
35 DiagnosticOnConstOnlyForTraitImpls { target_span },
36 span,
37 );
38 return;
39 }
40
4127 let mode = Mode::DiagnosticOnConst;
4228
4329 let Some(items) = parse_list(cx, args, mode) else { return };
......@@ -51,7 +37,11 @@ impl AttributeParser for OnConstParser {
5137
5238 // "Allowed" on all targets; noop on anything but non-const trait impls;
5339 // this linted on in parser.
54 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
40 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
41 // FIXME(mejrs) no constness field on `Target`,
42 // so non-constness is still checked in check_attr.rs
43 Allow(Target::Impl { of_trait: true }),
44 ]);
5545
5646 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
5747 if let Some(span) = self.span {
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs+6-10
......@@ -1,14 +1,12 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::attrs::AttributeKind;
3use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
43use rustc_span::sym;
54
65use crate::attributes::diagnostic::*;
76use crate::attributes::prelude::*;
87use crate::context::AcceptContext;
9use crate::diagnostics::DiagnosticOnMoveOnlyForAdt;
108use crate::parser::ArgParser;
11use crate::target_checking::{ALL_TARGETS, AllowedTargets};
9use crate::target_checking::AllowedTargets;
1210use crate::template;
1311
1412#[derive(Default)]
......@@ -28,11 +26,6 @@ impl OnMoveParser {
2826 let span = cx.attr_span;
2927 self.span = Some(span);
3028
31 if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) {
32 cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnMoveOnlyForAdt, span);
33 return;
34 }
35
3629 let Some(items) = parse_list(cx, args, mode) else { return };
3730
3831 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
......@@ -50,8 +43,11 @@ impl AttributeParser for OnMoveParser {
5043 },
5144 )];
5245
53 // "Allowed" for all targets but noop if used on not-adt.
54 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
46 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
47 Allow(Target::Enum),
48 Allow(Target::Struct),
49 Allow(Target::Union),
50 ]);
5551
5652 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
5753 if let Some(_span) = self.span {
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_type_error.rs+6-9
......@@ -1,14 +1,12 @@
11use rustc_hir::attrs::AttributeKind;
2use rustc_lint_defs::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
32use rustc_span::sym;
43
54use crate::attributes::AttributeStability;
65use crate::attributes::diagnostic::*;
76use crate::attributes::prelude::*;
87use crate::context::AcceptContext;
9use crate::diagnostics::DiagnosticOnTypeErrorOnlyForAdt;
108use crate::parser::ArgParser;
11use crate::target_checking::{ALL_TARGETS, AllowedTargets};
9use crate::target_checking::AllowedTargets;
1210use crate::template;
1311
1412#[derive(Default)]
......@@ -26,11 +24,6 @@ impl OnTypeErrorParser {
2624 let span = cx.attr_span;
2725 self.span = Some(span);
2826
29 if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) {
30 cx.emit_lint(MISPLACED_DIAGNOSTIC_ATTRIBUTES, DiagnosticOnTypeErrorOnlyForAdt, span);
31 return;
32 }
33
3427 let Some(items) = parse_list(cx, args, mode) else { return };
3528
3629 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
......@@ -49,7 +42,11 @@ impl AttributeParser for OnTypeErrorParser {
4942 },
5043 )];
5144
52 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
45 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
46 Allow(Target::Enum),
47 Allow(Target::Struct),
48 Allow(Target::Union),
49 ]);
5350
5451 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
5552 if let Some(span) = self.span {
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unimplemented.rs+2-13
......@@ -1,10 +1,8 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::attrs::diagnostic::Directive;
3use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
43
54use crate::attributes::diagnostic::*;
65use crate::attributes::prelude::*;
7use crate::diagnostics::DiagnosticOnUnimplementedOnlyForTraits;
86
97#[derive(Default)]
108pub(crate) struct OnUnimplementedParser {
......@@ -17,15 +15,6 @@ impl OnUnimplementedParser {
1715 let span = cx.attr_span;
1816 self.span = Some(span);
1917
20 if !matches!(cx.target, Target::Trait) {
21 cx.emit_lint(
22 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
23 DiagnosticOnUnimplementedOnlyForTraits,
24 span,
25 );
26 return;
27 }
28
2918 let Some(items) = parse_list(cx, args, mode) else { return };
3019
3120 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
......@@ -56,8 +45,8 @@ impl AttributeParser for OnUnimplementedParser {
5645 },
5746 ),
5847 ];
59 //FIXME attribute is not parsed for non-traits but diagnostics are issued in `check_attr.rs`
60 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
48 const ALLOWED_TARGETS: AllowedTargets =
49 AllowedTargets::AllowListWarnRest(&[Allow(Target::Trait)]);
6150
6251 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
6352 if let Some(_span) = self.span {
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unknown.rs+5-18
......@@ -1,11 +1,8 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::attrs::diagnostic::Directive;
3use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
43
5use crate::ShouldEmit;
64use crate::attributes::diagnostic::*;
75use crate::attributes::prelude::*;
8use crate::diagnostics::DiagnosticOnUnknownInvalidTarget;
96
107#[derive(Default)]
118pub(crate) struct OnUnknownParser {
......@@ -25,20 +22,6 @@ impl OnUnknownParser {
2522 let span = cx.attr_span;
2623 self.span = Some(span);
2724
28 // At early parsing we get passed `Target::Crate` regardless of the item we're on.
29 // Therefore, only do target checking if we can emit.
30 let early = matches!(cx.should_emit, ShouldEmit::Nothing);
31
32 if !early && !matches!(cx.target, Target::Use | Target::Mod | Target::Crate) {
33 let target_span = cx.target_span;
34 cx.emit_lint(
35 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
36 DiagnosticOnUnknownInvalidTarget { target_span },
37 span,
38 );
39 return;
40 }
41
4225 let Some(items) = parse_list(cx, args, mode) else { return };
4326
4427 if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) {
......@@ -57,7 +40,11 @@ impl AttributeParser for OnUnknownParser {
5740 },
5841 )];
5942 // "Allowed" for all targets, but noop for all but use statements.
60 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
43 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
44 Allow(Target::Use),
45 Allow(Target::Mod),
46 Allow(Target::Crate),
47 ]);
6148
6249 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
6350 if let Some(_span) = self.span {
compiler/rustc_attr_parsing/src/attributes/diagnostic/on_unmatched_args.rs+2-12
......@@ -1,10 +1,8 @@
11use rustc_feature::AttributeStability;
22use rustc_hir::attrs::diagnostic::Directive;
3use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
43
54use crate::attributes::diagnostic::*;
65use crate::attributes::prelude::*;
7use crate::diagnostics::DiagnosticOnUnmatchedArgsOnlyForMacros;
86
97#[derive(Default)]
108pub(crate) struct OnUnmatchedArgsParser {
......@@ -25,15 +23,6 @@ impl AttributeParser for OnUnmatchedArgsParser {
2523 let span = cx.attr_span;
2624 this.span = Some(span);
2725
28 if !matches!(cx.target, Target::MacroDef) {
29 cx.emit_lint(
30 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
31 DiagnosticOnUnmatchedArgsOnlyForMacros,
32 span,
33 );
34 return;
35 }
36
3726 let mode = Mode::DiagnosticOnUnmatchedArgs;
3827 let Some(items) = parse_list(cx, args, mode) else { return };
3928
......@@ -44,7 +33,8 @@ impl AttributeParser for OnUnmatchedArgsParser {
4433 },
4534 )];
4635
47 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
36 const ALLOWED_TARGETS: AllowedTargets =
37 AllowedTargets::AllowListWarnRest(&[Allow(Target::MacroDef)]);
4838
4939 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
5040 if let Some(_span) = self.span {
compiler/rustc_attr_parsing/src/diagnostics.rs-39
......@@ -279,45 +279,6 @@ pub(crate) struct UnknownCrateTypesSuggestion {
279279 pub snippet: Symbol,
280280}
281281
282#[derive(Diagnostic)]
283#[diag("`#[diagnostic::on_const]` can only be applied to non-const trait implementations")]
284pub(crate) struct DiagnosticOnConstOnlyForTraitImpls {
285 #[label("not a trait implementation")]
286 pub target_span: Span,
287}
288
289#[derive(Diagnostic)]
290#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")]
291pub(crate) struct DiagnosticOnMoveOnlyForAdt;
292
293#[derive(Diagnostic)]
294#[diag("`#[diagnostic::on_unimplemented]` can only be applied to trait definitions")]
295pub(crate) struct DiagnosticOnUnimplementedOnlyForTraits;
296
297#[derive(Diagnostic)]
298#[diag(
299 "`#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations"
300)]
301pub(crate) struct DiagnosticOnUnknownInvalidTarget {
302 #[label("not an import or module")]
303 pub target_span: Span,
304}
305
306#[derive(Diagnostic)]
307#[diag("`#[diagnostic::on_unmatched_args]` can only be applied to macro definitions")]
308pub(crate) struct DiagnosticOnUnmatchedArgsOnlyForMacros;
309
310#[derive(Diagnostic)]
311#[diag("`#[diagnostic::on_type_error]` can only be applied to enums, structs or unions")]
312pub(crate) struct DiagnosticOnTypeErrorOnlyForAdt;
313
314#[derive(Diagnostic)]
315#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")]
316pub(crate) struct IncorrectDoNotRecommendLocation {
317 #[label("not a trait implementation")]
318 pub target_span: Span,
319}
320
321282#[derive(Diagnostic)]
322283#[diag("malformed `doc` attribute input")]
323284#[warning(
compiler/rustc_attr_parsing/src/target_checking.rs+4-1
......@@ -129,6 +129,7 @@ impl<'sess> AttributeParser<'sess> {
129129
130130 let allowed_targets = allowed_targets.allowed_targets();
131131 let (applied, only) = allowed_targets_applied(allowed_targets, cx.target, cx.features);
132 let is_diagnostic_attr = cx.attr_path.segments[0] == sym::diagnostic;
132133
133134 let diag = InvalidTarget {
134135 span: cx.attr_span.clone(),
......@@ -138,7 +139,7 @@ impl<'sess> AttributeParser<'sess> {
138139 applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()),
139140 attribute_args,
140141 help: Self::target_checking_help(attribute_args, cx),
141 previously_accepted: matches!(result, AllowedResult::Warn),
142 previously_accepted: matches!(result, AllowedResult::Warn) && !is_diagnostic_attr,
142143 on_macro_call: matches!(cx.target, Target::MacroCall),
143144 };
144145
......@@ -156,6 +157,8 @@ impl<'sess> AttributeParser<'sess> {
156157 .contains(&cx.target)
157158 {
158159 rustc_session::lint::builtin::USELESS_DEPRECATED
160 } else if is_diagnostic_attr {
161 rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES
159162 } else {
160163 rustc_session::lint::builtin::UNUSED_ATTRIBUTES
161164 };
compiler/rustc_codegen_ssa/src/back/linker.rs+1-1
......@@ -1862,7 +1862,7 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, Symbol
18621862 }
18631863
18641864 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
1865 let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
1865 let proc_macro_decls_name = rustc_session::generate_proc_macro_decls_symbol(stable_crate_id);
18661866
18671867 vec![(proc_macro_decls_name, SymbolExportKind::Data)]
18681868}
compiler/rustc_metadata/src/creader.rs+2-140
......@@ -1,10 +1,8 @@
11//! Validates all used crates and extern libraries and loads their metadata
22
33use std::collections::BTreeMap;
4use std::error::Error;
54use std::path::Path;
65use std::str::FromStr;
7use std::time::Duration;
86use std::{cmp, env, iter};
97
108use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, AllocatorKind, global_fn_name};
......@@ -15,7 +13,6 @@ use rustc_data_structures::svh::Svh;
1513use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard};
1614use rustc_data_structures::unord::UnordMap;
1715use rustc_expand::base::SyntaxExtension;
18use rustc_fs_util::try_canonicalize;
1916use rustc_hir as hir;
2017use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId};
2118use rustc_hir::definitions::Definitions;
......@@ -653,7 +650,7 @@ impl CStore {
653650 None => (&source, &crate_root),
654651 };
655652 let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
656 Some(self.dlsym_proc_macros(tcx.sess, dlsym_dylib, dlsym_root.stable_crate_id())?)
653 Some(self.dlsym_proc_macros(dlsym_dylib, dlsym_root.stable_crate_id())?)
657654 } else {
658655 None
659656 };
......@@ -948,31 +945,10 @@ impl CStore {
948945
949946 fn dlsym_proc_macros(
950947 &self,
951 sess: &Session,
952948 path: &Path,
953949 stable_crate_id: StableCrateId,
954950 ) -> Result<&'static [ProcMacroClient], CrateError> {
955 let sym_name = sess.generate_proc_macro_decls_symbol(stable_crate_id);
956 debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
957
958 unsafe {
959 // FIXME(bjorn3) this depends on the unstable slice memory layout
960 let result = load_symbol_from_dylib::<*const &[ProcMacroClient]>(path, &sym_name);
961 match result {
962 Ok(result) => {
963 debug!("loaded dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
964 Ok(*result)
965 }
966 Err(err) => {
967 debug!(
968 "failed to dlsym proc_macros {} for symbol `{}`",
969 path.display(),
970 sym_name
971 );
972 Err(err.into())
973 }
974 }
975 }
951 Ok(crate::host_dylib::dlsym_proc_macros(path, stable_crate_id)?)
976952 }
977953
978954 fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
......@@ -1415,117 +1391,3 @@ fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec<Span> {
14151391 visit::walk_crate(&mut f, krate);
14161392 f.spans
14171393}
1418
1419fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String {
1420 e.sources().map(|e| format!(": {e}")).collect()
1421}
1422
1423fn attempt_load_dylib(path: &Path) -> Result<libloading::Library, libloading::Error> {
1424 #[cfg(target_os = "aix")]
1425 if let Some(ext) = path.extension()
1426 && ext.eq("a")
1427 {
1428 // On AIX, we ship all libraries as .a big_af archive
1429 // the expected format is lib<name>.a(libname.so) for the actual
1430 // dynamic library
1431 let library_name = path.file_stem().expect("expect a library name");
1432 let mut archive_member = std::ffi::OsString::from("a(");
1433 archive_member.push(library_name);
1434 archive_member.push(".so)");
1435 let new_path = path.with_extension(archive_member);
1436
1437 // On AIX, we need RTLD_MEMBER to dlopen an archived shared
1438 let flags = libc::RTLD_LAZY | libc::RTLD_LOCAL | libc::RTLD_MEMBER;
1439 return unsafe { libloading::os::unix::Library::open(Some(&new_path), flags) }
1440 .map(|lib| lib.into());
1441 }
1442
1443 unsafe { libloading::Library::new(&path) }
1444}
1445
1446// On Windows the compiler would sometimes intermittently fail to open the
1447// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
1448// system still holds a lock on the file, so we retry a few times before calling it
1449// an error.
1450fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
1451 assert!(max_attempts > 0);
1452
1453 let mut last_error = None;
1454
1455 for attempt in 0..max_attempts {
1456 debug!("Attempt to load proc-macro `{}`.", path.display());
1457 match attempt_load_dylib(path) {
1458 Ok(lib) => {
1459 if attempt > 0 {
1460 debug!(
1461 "Loaded proc-macro `{}` after {} attempts.",
1462 path.display(),
1463 attempt + 1
1464 );
1465 }
1466 return Ok(lib);
1467 }
1468 Err(err) => {
1469 // Only try to recover from this specific error.
1470 if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
1471 debug!("Failed to load proc-macro `{}`. Not retrying", path.display());
1472 let err = format_dlopen_err(&err);
1473 // We include the path of the dylib in the error ourselves, so
1474 // if it's in the error, we strip it.
1475 if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) {
1476 return Err(err.to_string());
1477 }
1478 return Err(err);
1479 }
1480
1481 last_error = Some(err);
1482 std::thread::sleep(Duration::from_millis(100));
1483 debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
1484 }
1485 }
1486 }
1487
1488 debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
1489
1490 let last_error = last_error.unwrap();
1491 let message = if let Some(src) = last_error.source() {
1492 format!("{} ({src}) (retried {max_attempts} times)", format_dlopen_err(&last_error))
1493 } else {
1494 format!("{} (retried {max_attempts} times)", format_dlopen_err(&last_error))
1495 };
1496 Err(message)
1497}
1498
1499pub enum DylibError {
1500 DlOpen(String, String),
1501 DlSym(String, String),
1502}
1503
1504impl From<DylibError> for CrateError {
1505 fn from(err: DylibError) -> CrateError {
1506 match err {
1507 DylibError::DlOpen(path, err) => CrateError::DlOpen(path, err),
1508 DylibError::DlSym(path, err) => CrateError::DlSym(path, err),
1509 }
1510 }
1511}
1512
1513pub unsafe fn load_symbol_from_dylib<T: Copy>(
1514 path: &Path,
1515 sym_name: &str,
1516) -> Result<T, DylibError> {
1517 // Make sure the path contains a / or the linker will search for it.
1518 let path = try_canonicalize(path).unwrap();
1519 let lib =
1520 load_dylib(&path, 5).map_err(|err| DylibError::DlOpen(path.display().to_string(), err))?;
1521
1522 let sym = unsafe { lib.get::<T>(sym_name.as_bytes()) }
1523 .map_err(|err| DylibError::DlSym(path.display().to_string(), format_dlopen_err(&err)))?;
1524
1525 // Intentionally leak the dynamic library. We can't ever unload it
1526 // since the library can make things that will live arbitrarily long.
1527 let sym = unsafe { sym.into_raw() };
1528 std::mem::forget(lib);
1529
1530 Ok(*sym)
1531}
compiler/rustc_metadata/src/host_dylib.rs created+147
......@@ -0,0 +1,147 @@
1use std::error::Error;
2use std::path::Path;
3use std::time::Duration;
4
5use rustc_fs_util::try_canonicalize;
6use rustc_proc_macro::bridge::client::Client as ProcMacroClient;
7use rustc_session::StableCrateId;
8use tracing::debug;
9
10use crate::locator::CrateError;
11
12fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String {
13 e.sources().map(|e| format!(": {e}")).collect()
14}
15
16fn attempt_load_dylib(path: &Path) -> Result<libloading::Library, libloading::Error> {
17 #[cfg(target_os = "aix")]
18 if let Some(ext) = path.extension()
19 && ext.eq("a")
20 {
21 // On AIX, we ship all libraries as .a big_af archive
22 // the expected format is lib<name>.a(libname.so) for the actual
23 // dynamic library
24 let library_name = path.file_stem().expect("expect a library name");
25 let mut archive_member = std::ffi::OsString::from("a(");
26 archive_member.push(library_name);
27 archive_member.push(".so)");
28 let new_path = path.with_extension(archive_member);
29
30 // On AIX, we need RTLD_MEMBER to dlopen an archived shared
31 let flags = libc::RTLD_LAZY | libc::RTLD_LOCAL | libc::RTLD_MEMBER;
32 return unsafe { libloading::os::unix::Library::open(Some(&new_path), flags) }
33 .map(|lib| lib.into());
34 }
35
36 unsafe { libloading::Library::new(&path) }
37}
38
39// On Windows the compiler would sometimes intermittently fail to open the
40// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
41// system still holds a lock on the file, so we retry a few times before calling it
42// an error.
43fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
44 assert!(max_attempts > 0);
45
46 let mut last_error = None;
47
48 for attempt in 0..max_attempts {
49 debug!("Attempt to load proc-macro `{}`.", path.display());
50 match attempt_load_dylib(path) {
51 Ok(lib) => {
52 if attempt > 0 {
53 debug!(
54 "Loaded proc-macro `{}` after {} attempts.",
55 path.display(),
56 attempt + 1
57 );
58 }
59 return Ok(lib);
60 }
61 Err(err) => {
62 // Only try to recover from this specific error.
63 if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
64 debug!("Failed to load proc-macro `{}`. Not retrying", path.display());
65 let err = format_dlopen_err(&err);
66 // We include the path of the dylib in the error ourselves, so
67 // if it's in the error, we strip it.
68 if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) {
69 return Err(err.to_string());
70 }
71 return Err(err);
72 }
73
74 last_error = Some(err);
75 std::thread::sleep(Duration::from_millis(100));
76 debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
77 }
78 }
79 }
80
81 debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
82
83 let last_error = last_error.unwrap();
84 let message = if let Some(src) = last_error.source() {
85 format!("{} ({src}) (retried {max_attempts} times)", format_dlopen_err(&last_error))
86 } else {
87 format!("{} (retried {max_attempts} times)", format_dlopen_err(&last_error))
88 };
89 Err(message)
90}
91
92pub enum DylibError {
93 DlOpen(String, String),
94 DlSym(String, String),
95}
96
97impl From<DylibError> for CrateError {
98 fn from(err: DylibError) -> CrateError {
99 match err {
100 DylibError::DlOpen(path, err) => CrateError::DlOpen(path, err),
101 DylibError::DlSym(path, err) => CrateError::DlSym(path, err),
102 }
103 }
104}
105
106pub unsafe fn load_symbol_from_dylib<T: Copy>(
107 path: &Path,
108 sym_name: &str,
109) -> Result<T, DylibError> {
110 // Make sure the path contains a / or the linker will search for it.
111 let path = try_canonicalize(path).unwrap();
112 let lib =
113 load_dylib(&path, 5).map_err(|err| DylibError::DlOpen(path.display().to_string(), err))?;
114
115 let sym = unsafe { lib.get::<T>(sym_name.as_bytes()) }
116 .map_err(|err| DylibError::DlSym(path.display().to_string(), format_dlopen_err(&err)))?;
117
118 // Intentionally leak the dynamic library. We can't ever unload it
119 // since the library can make things that will live arbitrarily long.
120 let sym = unsafe { sym.into_raw() };
121 std::mem::forget(lib);
122
123 Ok(*sym)
124}
125
126pub(crate) fn dlsym_proc_macros(
127 path: &Path,
128 stable_crate_id: StableCrateId,
129) -> Result<&'static [ProcMacroClient], DylibError> {
130 let sym_name = rustc_session::generate_proc_macro_decls_symbol(stable_crate_id);
131 debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
132
133 unsafe {
134 // FIXME(bjorn3) this depends on the unstable slice memory layout
135 let result = crate::load_symbol_from_dylib::<*const &[ProcMacroClient]>(path, &sym_name);
136 match result {
137 Ok(result) => {
138 debug!("loaded dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
139 Ok(*result)
140 }
141 Err(err) => {
142 debug!("failed to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name);
143 Err(err.into())
144 }
145 }
146 }
147}
compiler/rustc_metadata/src/lib.rs+2-1
......@@ -17,6 +17,7 @@ pub use rmeta::provide;
1717mod dependency_format;
1818mod eii;
1919mod foreign_modules;
20mod host_dylib;
2021mod native_libs;
2122mod rmeta;
2223
......@@ -25,8 +26,8 @@ pub mod diagnostics;
2526pub mod fs;
2627pub mod locator;
2728
28pub use creader::{DylibError, load_symbol_from_dylib};
2929pub use fs::{METADATA_FILENAME, emit_wrapper_file};
30pub use host_dylib::{DylibError, load_symbol_from_dylib};
3031pub use native_libs::{
3132 NativeLibSearchFallback, find_native_static_library, try_find_native_dynamic_library,
3233 try_find_native_static_library, walk_native_lib_search_dirs,
compiler/rustc_metadata/src/locator.rs+22-10
......@@ -213,7 +213,7 @@
213213//! metadata::locator or metadata::creader for all the juicy details!
214214
215215use std::borrow::Cow;
216use std::io::{Result as IoResult, Write};
216use std::io::{self, Result as IoResult, Write};
217217use std::ops::Deref;
218218use std::path::{Path, PathBuf};
219219use std::{cmp, fmt};
......@@ -224,6 +224,7 @@ use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
224224use rustc_data_structures::svh::Svh;
225225use rustc_errors::{DiagArgValue, IntoDiagArg};
226226use rustc_fs_util::try_canonicalize;
227use rustc_proc_macro::bridge::client::Client as ProcMacroClient;
227228use rustc_session::cstore::CrateSource;
228229use rustc_session::filesearch::FileSearch;
229230use rustc_session::search_paths::PathKind;
......@@ -821,7 +822,7 @@ fn get_metadata_section<'p>(
821822 crate_name: Option<Symbol>,
822823) -> Result<MetadataBlob, MetadataError<'p>> {
823824 if !filename.exists() {
824 return Err(MetadataError::NotPresent(filename.into()));
825 return Err(MetadataError::NotPresent(filename));
825826 }
826827 let raw_bytes = match flavor {
827828 CrateFlavor::Rlib => {
......@@ -978,18 +979,29 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor {
978979 }
979980}
980981
981/// A function to get information about all macros inside a proc-macro crate.
982/// A function to fetch about all macros inside a proc-macro crate.
982983///
983984/// Used by rust-analyzer-proc-macro-srv.
984pub fn get_proc_macro_info<'p>(
985pub fn get_proc_macros(
985986 target: &Target,
986 path: &'p Path,
987 path: &Path,
987988 metadata_loader: &dyn MetadataLoader,
988989 cfg_version: &'static str,
989) -> Result<Vec<ProcMacroKind>, MetadataError<'p>> {
990) -> IoResult<Vec<(ProcMacroClient, ProcMacroKind)>> {
990991 let metadata =
991 get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)?;
992 Ok(metadata.get_proc_macro_info())
992 get_metadata_section(target, CrateFlavor::Dylib, path, metadata_loader, cfg_version, None)
993 .map_err(|err| io::Error::other(err.to_string()))?;
994 let stable_crate_id = metadata.get_root().stable_crate_id();
995
996 let clients = crate::host_dylib::dlsym_proc_macros(path, stable_crate_id).map_err(|err| {
997 let (crate::DylibError::DlOpen(path, err) | crate::DylibError::DlSym(path, err)) = err;
998 io::Error::other(format!("{path}{err}"))
999 })?;
1000
1001 let proc_macro_info = metadata.get_proc_macro_info();
1002 assert_eq!(proc_macro_info.len(), clients.len());
1003
1004 Ok(clients.into_iter().copied().zip(proc_macro_info).collect())
9931005}
9941006
9951007// ------------------------------------------ Error reporting -------------------------------------
......@@ -1039,9 +1051,9 @@ pub(crate) enum CrateError {
10391051}
10401052
10411053#[derive(Debug)]
1042pub enum MetadataError<'a> {
1054pub(crate) enum MetadataError<'a> {
10431055 /// The file was missing.
1044 NotPresent(Cow<'a, Path>),
1056 NotPresent(&'a Path),
10451057 /// The file was present and invalid.
10461058 LoadFailure(String),
10471059 /// The file was present, but compiled with a different rustc version.
compiler/rustc_mir_transform/src/simplify_comparison_integral.rs+18-28
......@@ -76,30 +76,24 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
7676 _ => unreachable!(),
7777 }
7878
79 // delete comparison statement if it the value being switched on was moved, which means
80 // it can not be used later on
81 if opt.can_remove_bin_op_stmt {
82 bb.statements[opt.bin_op_stmt_idx].make_nop(true);
83 } else {
84 // if the integer being compared to a const integral is being moved into the
85 // comparison, e.g `_2 = Eq(move _3, const 'x');`
86 // we want to avoid making a double move later on in the switchInt on _3.
87 // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`,
88 // we convert the move in the comparison statement to a copy.
89
90 // unwrap is safe as we know this statement is an assign
91 let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap();
92
93 use Operand::*;
94 match rhs {
95 Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => {
96 *left = Copy(opt.to_switch_on);
97 }
98 Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => {
99 *right = Copy(opt.to_switch_on);
100 }
101 _ => (),
79 // if the integer being compared to a const integral is being moved into the
80 // comparison, e.g `_2 = Eq(move _3, const 'x');`
81 // we want to avoid making a double move later on in the switchInt on _3.
82 // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`,
83 // we convert the move in the comparison statement to a copy.
84
85 // unwrap is safe as we know this statement is an assign
86 let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap();
87
88 use Operand::*;
89 match rhs {
90 Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => {
91 *left = Copy(opt.to_switch_on);
92 }
93 Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => {
94 *right = Copy(opt.to_switch_on);
10295 }
96 _ => (),
10397 }
10498
10599 let terminator = bb.terminator();
......@@ -184,7 +178,6 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> {
184178 Some(OptimizationInfo {
185179 bin_op_stmt_idx: stmt_idx,
186180 bb_idx,
187 can_remove_bin_op_stmt: discr.is_move(),
188181 to_switch_on,
189182 branch_value_scalar,
190183 branch_value_ty,
......@@ -235,11 +228,8 @@ fn find_branch_value_info<'tcx>(
235228struct OptimizationInfo<'tcx> {
236229 /// Basic block to apply the optimization
237230 bb_idx: BasicBlock,
238 /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be
239 /// removed - i.e the statement is used later on
231 /// Statement index of Eq/Ne assignment
240232 bin_op_stmt_idx: usize,
241 /// Can remove Eq/Ne assignment
242 can_remove_bin_op_stmt: bool,
243233 /// Place that needs to be switched on. This place is of type integral
244234 to_switch_on: Place<'tcx>,
245235 /// Constant to use in switch target value
compiler/rustc_session/src/session.rs+4-4
......@@ -420,10 +420,6 @@ impl Session {
420420 self.target.debuginfo_kind == DebuginfoKind::Dwarf
421421 }
422422
423 pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
424 format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64())
425 }
426
427423 pub fn target_filesearch(&self) -> &filesearch::FileSearch {
428424 &self.target_filesearch
429425 }
......@@ -1149,6 +1145,10 @@ pub fn build_session(
11491145 sess
11501146}
11511147
1148pub fn generate_proc_macro_decls_symbol(stable_crate_id: StableCrateId) -> String {
1149 format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.as_u64())
1150}
1151
11521152/// Validate command line arguments with a `Session`.
11531153///
11541154/// If it is useful to have a Session available already for validating a commandline argument, you
compiler/rustc_symbol_mangling/src/lib.rs+1-1
......@@ -165,7 +165,7 @@ fn compute_symbol_name<'tcx>(
165165 if let Some(def_id) = def_id.as_local() {
166166 if tcx.proc_macro_decls_static(()) == Some(def_id) {
167167 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
168 return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
168 return rustc_session::generate_proc_macro_decls_symbol(stable_crate_id);
169169 }
170170 }
171171
compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs+5
......@@ -40,6 +40,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
4040 if trait_pred.polarity() != ty::PredicatePolarity::Positive {
4141 return CustomDiagnostic::default();
4242 }
43 // This is needed as `on_unimplemented` is currently not allowed on trait aliases,
44 // but the "not allowed" is a warning, and this check ensures the attribute has no effect
45 if self.tcx.is_trait_alias(trait_pred.def_id()) {
46 return CustomDiagnostic::default();
47 }
4348 let (filter_options, format_args) =
4449 self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
4550 if let Some(command) = find_attr!(self.tcx, trait_pred.def_id(), OnUnimplemented {directive, ..} => directive.as_deref()).flatten() {
library/backtrace+1-1
......@@ -1 +1 @@
1Subproject commit 28ec93b503bf0410745bc3d571bf3dc1caac3019
1Subproject commit d902726a1dcdc1e1c66f73d1162181b5423c645b
src/bootstrap/src/core/build_steps/llvm.rs+5-5
......@@ -169,7 +169,7 @@ pub fn prebuilt_llvm_config(
169169 generate_smart_stamp_hash(
170170 builder,
171171 &builder.config.src.join("src/llvm-project"),
172 builder.in_tree_llvm_info.sha().unwrap_or_default(),
172 &builder.llvm_cache_key(),
173173 )
174174 });
175175
......@@ -999,7 +999,7 @@ impl Step for OmpOffload {
999999 generate_smart_stamp_hash(
10001000 builder,
10011001 &builder.config.src.join("src/llvm-project/offload"),
1002 builder.in_tree_llvm_info.sha().unwrap_or_default(),
1002 &builder.llvm_cache_key(),
10031003 )
10041004 });
10051005 let stamp = BuildStamp::new(&out_dir).with_prefix("offload").add_stamp(smart_stamp_hash);
......@@ -1166,8 +1166,8 @@ impl Step for Enzyme {
11661166 // Enzyme links against LLVM. If we update the LLVM submodule libLLVM might get a new
11671167 // version number, in which case Enzyme will now fail to find LLVM. By including the LLVM
11681168 // hash into the Enzyme hash we force a rebuild of Enzyme when updating LLVM.
1169 let enzyme_hash_input = builder.in_tree_llvm_info.sha().unwrap_or_default().to_owned()
1170 + builder.enzyme_info.sha().unwrap_or_default();
1169 let enzyme_hash_input =
1170 builder.llvm_cache_key() + builder.enzyme_info.sha().unwrap_or_default();
11711171
11721172 static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
11731173 let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
......@@ -1430,7 +1430,7 @@ impl Step for Sanitizers {
14301430 generate_smart_stamp_hash(
14311431 builder,
14321432 &builder.config.src.join("src/llvm-project/compiler-rt"),
1433 builder.in_tree_llvm_info.sha().unwrap_or_default(),
1433 &builder.llvm_cache_key(),
14341434 )
14351435 });
14361436
src/bootstrap/src/core/build_steps/test.rs+134
......@@ -992,6 +992,140 @@ impl Step for StdarchVerify {
992992 }
993993}
994994
995/// Runs stdarch's intrinsic-test binary crate to verify that Rust's `core::arch`
996/// SIMD intrinsics produce the same results as their C counterparts.
997///
998/// First runs the `intrinsic-test` binary, which generates C wrapper programs
999/// and a Rust Cargo workspace. Then runs `cargo test` on that workspace
1000/// which compiles both versions and compares their outputs on random inputs.
1001#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1002pub struct IntrinsicTest {
1003 host: TargetSelection,
1004}
1005
1006impl Step for IntrinsicTest {
1007 type Output = ();
1008 const IS_HOST: bool = true;
1009
1010 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1011 run.path("library/stdarch/crates/intrinsic-test")
1012 }
1013
1014 fn make_run(run: RunConfig<'_>) {
1015 let target = run.target;
1016 if !target.contains("aarch64-unknown-linux") && !target.contains("x86_64-unknown-linux") {
1017 return;
1018 }
1019 run.builder.ensure(IntrinsicTest { host: target });
1020 }
1021
1022 fn run(self, builder: &Builder<'_>) {
1023 let host = self.host;
1024
1025 let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
1026 let cpuid_def =
1027 builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def");
1028 let sde_runner = format!(
1029 "/intel-sde/sde64 -cpuid-in {} -rtm-mode full -tsx --",
1030 cpuid_def.display()
1031 );
1032 (
1033 builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"),
1034 [
1035 builder
1036 .src
1037 .join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"),
1038 builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"),
1039 ],
1040 "-I/usr/include/x86_64-linux-gnu/",
1041 Some(sde_runner),
1042 )
1043 } else if host.contains("aarch64-unknown-linux") {
1044 (
1045 builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"),
1046 [
1047 builder
1048 .src
1049 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"),
1050 builder
1051 .src
1052 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"),
1053 ],
1054 "-I/usr/aarch64-linux-gnu/include/",
1055 None,
1056 )
1057 } else {
1058 panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}");
1059 };
1060
1061 let out_dir = builder.out.join(host).join("intrinsic-test");
1062 t!(fs::create_dir_all(&out_dir));
1063
1064 let crates_link = out_dir.join("crates");
1065 if !crates_link.exists() {
1066 t!(
1067 helpers::symlink_dir(
1068 &builder.config,
1069 &builder.src.join("library/stdarch/crates"),
1070 &crates_link
1071 ),
1072 format!("failed to symlink stdarch crates into {}", crates_link.display())
1073 );
1074 }
1075
1076 let mut cmd = builder.tool_cmd(Tool::IntrinsicTest);
1077 cmd.current_dir(&out_dir);
1078 cmd.arg(&input_file);
1079 cmd.arg("--target").arg(&*host.triple);
1080 for skip in &skip_file {
1081 cmd.arg("--skip").arg(skip);
1082 }
1083 cmd.arg("--sample-percentage").arg("10");
1084 cmd.arg("--cc-arg-style").arg("gcc");
1085 cmd.env("CC", builder.cc(host));
1086 cmd.env("CFLAGS", cflags);
1087 // intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's
1088 // managed binaries findable by prepending their dirs to PATH.
1089 let rustfmt_path = builder.config.initial_rustfmt.clone().unwrap_or_else(|| {
1090 eprintln!("intrinsic-test: rustfmt is required but not available on this channel");
1091 crate::exit!(1);
1092 });
1093
1094 let mut path_dirs: Vec<PathBuf> = Vec::new();
1095 if let Some(cargo_dir) = builder.initial_cargo.parent() {
1096 path_dirs.push(cargo_dir.to_path_buf());
1097 }
1098 if let Some(rustfmt_dir) = rustfmt_path.parent() {
1099 path_dirs.push(rustfmt_dir.to_path_buf());
1100 }
1101 let old_path = env::var_os("PATH").unwrap_or_default();
1102 let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path)))
1103 .expect("could not build PATH for intrinsic-test");
1104 cmd.env("PATH", new_path);
1105 cmd.run(builder);
1106
1107 let tested_compiler = builder.compiler(builder.top_stage, host);
1108 builder.std(tested_compiler, host);
1109 let rustc = builder.rustc(tested_compiler);
1110
1111 let manifest = out_dir.join("rust_programs/Cargo.toml");
1112 let mut cargo = command(&builder.initial_cargo);
1113 cargo.arg("test");
1114 cargo.arg("--tests");
1115 cargo.arg("--manifest-path").arg(&manifest);
1116 cargo.arg("--target").arg(&*host.triple);
1117 cargo.arg("--profile").arg("release");
1118 cargo.env("CC", builder.cc(host));
1119 cargo.env("CFLAGS", cflags);
1120 cargo.env("RUSTC", rustc);
1121 cargo.env("RUSTC_BOOTSTRAP", "1");
1122 if let Some(runner) = sde_runner {
1123 cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner);
1124 }
1125 cargo.run(builder);
1126 }
1127}
1128
9951129#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9961130pub struct Clippy {
9971131 compilers: RustcPrivateCompilers,
src/bootstrap/src/core/build_steps/tool.rs+1
......@@ -508,6 +508,7 @@ bootstrap_tool!(
508508 FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
509509 OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
510510 RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
511 IntrinsicTest, "library/stdarch/crates/intrinsic-test", "intrinsic-test";
511512);
512513
513514/// These are the submodules that are required for rustbook to work due to
src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_library.snap+3
......@@ -21,3 +21,6 @@ expression: test library
2121[Test] test::StdarchVerify
2222 targets: [x86_64-unknown-linux-gnu]
2323 - Set({test::library/stdarch/crates/stdarch-verify})
24[Test] test::IntrinsicTest
25 targets: [x86_64-unknown-linux-gnu]
26 - Set({test::library/stdarch/crates/intrinsic-test})
src/bootstrap/src/core/builder/mod.rs+11
......@@ -911,6 +911,7 @@ impl<'a> Builder<'a> {
911911 test::Clippy,
912912 test::CompiletestTest,
913913 test::StdarchVerify,
914 test::IntrinsicTest,
914915 test::CrateRunMakeSupport,
915916 test::CrateBuildHelper,
916917 test::RustdocJSStd,
......@@ -1686,6 +1687,16 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler
16861687 pub fn exec_ctx(&self) -> &ExecutionContext {
16871688 &self.config.exec_ctx
16881689 }
1690
1691 /// When to rebuild LLVM. Currently includes the LLVM commit hash and the configuration from
1692 /// bootstrap.toml.
1693 pub(crate) fn llvm_cache_key(&self) -> String {
1694 format!(
1695 "sha={sha}\nkey={key}",
1696 sha = self.in_tree_llvm_info.sha().unwrap_or_default(),
1697 key = self.config.llvm_cache_key,
1698 )
1699 }
16891700}
16901701
16911702/// Return qualified step name, e.g. `compile::Rustc`.
src/bootstrap/src/core/config/config.rs+7-1
......@@ -156,6 +156,9 @@ pub struct Config {
156156 pub backtrace_on_ice: bool,
157157
158158 // llvm codegen options
159 /// Key used to decide when to rebuild LLVM.
160 pub llvm_cache_key: String,
161
159162 pub llvm_assertions: bool,
160163 pub llvm_tests: bool,
161164 pub llvm_enzyme: bool,
......@@ -595,6 +598,8 @@ impl Config {
595598 rustflags: rust_rustflags,
596599 } = toml.rust.unwrap_or_default();
597600
601 let llvm = toml.llvm.unwrap_or_default();
602 let llvm_cache_key = llvm.cache_key();
598603 let Llvm {
599604 optimize: llvm_optimize,
600605 thin_lto: llvm_thin_lto,
......@@ -625,7 +630,7 @@ impl Config {
625630 enable_warnings: llvm_enable_warnings,
626631 download_ci_llvm: llvm_download_ci_llvm,
627632 build_config: llvm_build_config,
628 } = toml.llvm.unwrap_or_default();
633 } = llvm;
629634
630635 let Dist {
631636 sign_folder: dist_sign_folder,
......@@ -1401,6 +1406,7 @@ impl Config {
14011406 llvm_assertions,
14021407 llvm_bitcode_linker_enabled: rust_llvm_bitcode_linker.unwrap_or(false),
14031408 llvm_build_config: llvm_build_config.clone().unwrap_or(Default::default()),
1409 llvm_cache_key,
14041410 llvm_cflags,
14051411 llvm_clang: llvm_clang.unwrap_or(false),
14061412 llvm_clang_cl,
src/bootstrap/src/core/config/toml/llvm.rs+87
......@@ -43,6 +43,93 @@ define_config! {
4343 }
4444}
4545
46impl Llvm {
47 /// A key that is used to determine whether LLVM should be rebuilt.
48 pub(crate) fn cache_key(&self) -> String {
49 let helper = || {
50 let mut key = String::with_capacity(512);
51
52 let Self {
53 optimize,
54 thin_lto,
55 release_debuginfo,
56 assertions,
57 tests,
58 enzyme,
59 plugins,
60 static_libstdcpp,
61 libzstd,
62 ninja,
63 targets,
64 experimental_targets,
65 link_jobs: _,
66 link_shared,
67 version_suffix,
68 clang_cl,
69 cflags,
70 cxxflags,
71 ldflags,
72 use_libcxx,
73 use_linker,
74 allow_old_toolchain,
75 offload,
76 polly,
77 offload_clang_dir,
78 clang,
79 enable_warnings: _,
80 build_config,
81 download_ci_llvm: _,
82 } = self;
83
84 use std::fmt::Write;
85 write!(key, "{:?}", optimize)?;
86 write!(key, "{:?}", thin_lto)?;
87 write!(key, "{:?}", release_debuginfo)?;
88 write!(key, "{:?}", assertions)?;
89 write!(key, "{:?}", tests)?;
90 write!(key, "{:?}", enzyme)?;
91 write!(key, "{:?}", plugins)?;
92 write!(key, "{:?}", static_libstdcpp)?;
93 write!(key, "{:?}", libzstd)?;
94 write!(key, "{:?}", ninja)?;
95 write!(key, "{:?}", targets)?;
96 write!(key, "{:?}", experimental_targets)?;
97 write!(key, "{:?}", link_shared)?;
98 write!(key, "{:?}", version_suffix)?;
99 write!(key, "{:?}", clang_cl)?;
100 write!(key, "{:?}", cflags)?;
101 write!(key, "{:?}", cxxflags)?;
102 write!(key, "{:?}", ldflags)?;
103 write!(key, "{:?}", use_libcxx)?;
104 write!(key, "{:?}", use_linker)?;
105 write!(key, "{:?}", allow_old_toolchain)?;
106 write!(key, "{:?}", offload)?;
107 write!(key, "{:?}", polly)?;
108 write!(key, "{:?}", offload_clang_dir)?;
109 write!(key, "{:?}", clang)?;
110
111 match build_config {
112 None => {
113 write!(key, "None")?;
114 }
115 Some(c) => {
116 let mut build_config = c.iter().collect::<Vec<_>>();
117 build_config.sort();
118
119 for (k, v) in build_config {
120 write!(key, "{}: {}", k, v)?;
121 }
122 }
123 }
124
125 Ok::<_, std::fmt::Error>(key)
126 };
127
128 // write! to a String always succeeds unless OOM.
129 helper().unwrap()
130 }
131}
132
46133/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
47134/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing.
48135#[cfg(not(test))]
src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile+8-1
......@@ -21,6 +21,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2121 libzstd-dev \
2222 && rm -rf /var/lib/apt/lists/*
2323
24# Install Intel SDE for AVX-512 emulation
25RUN curl -L http://ci-mirrors.rust-lang.org/sde-external-10.8.0-2026-03-15-lin.tar.xz -o /tmp/sde.tar.xz \
26 && mkdir -p /intel-sde \
27 && tar -xJf /tmp/sde.tar.xz --strip-components=1 -C /intel-sde \
28 && rm /tmp/sde.tar.xz
29
2430COPY scripts/sccache.sh /scripts/
2531RUN sh /scripts/sccache.sh
2632
......@@ -29,4 +35,5 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \
2935 --enable-profiler \
3036 --enable-compiler-docs \
3137 --set llvm.libzstd=true"
32ENV SCRIPT="python3 ../x.py --stage 2 test"
38ENV SCRIPT="python3 ../x.py --stage 2 test && \
39 python3 ../x.py --stage 2 test library/stdarch/crates/intrinsic-test"
\ No newline at end of file
src/tools/miri/Cargo.lock+46-21
......@@ -80,15 +80,6 @@ dependencies = [
8080 "windows-link 0.2.1",
8181]
8282
83[[package]]
84name = "bincode"
85version = "1.3.3"
86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
88dependencies = [
89 "serde",
90]
91
9283[[package]]
9384name = "bitflags"
9485version = "2.11.1"
......@@ -262,6 +253,15 @@ dependencies = [
262253 "cc",
263254]
264255
256[[package]]
257name = "cobs"
258version = "0.3.0"
259source = "registry+https://github.com/rust-lang/crates.io-index"
260checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
261dependencies = [
262 "thiserror 2.0.18",
263]
264
265265[[package]]
266266name = "codespan-reporting"
267267version = "0.13.1"
......@@ -460,6 +460,18 @@ dependencies = [
460460 "syn",
461461]
462462
463[[package]]
464name = "embedded-io"
465version = "0.4.0"
466source = "registry+https://github.com/rust-lang/crates.io-index"
467checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
468
469[[package]]
470name = "embedded-io"
471version = "0.6.1"
472source = "registry+https://github.com/rust-lang/crates.io-index"
473checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
474
463475[[package]]
464476name = "encode_unicode"
465477version = "1.0.0"
......@@ -504,12 +516,6 @@ version = "0.1.9"
504516source = "registry+https://github.com/rust-lang/crates.io-index"
505517checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
506518
507[[package]]
508name = "fnv"
509version = "1.0.7"
510source = "registry+https://github.com/rust-lang/crates.io-index"
511checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
512
513519[[package]]
514520name = "foldhash"
515521version = "0.1.5"
......@@ -805,18 +811,19 @@ dependencies = [
805811
806812[[package]]
807813name = "ipc-channel"
808version = "0.20.2"
814version = "0.22.0"
809815source = "registry+https://github.com/rust-lang/crates.io-index"
810checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180"
816checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61"
811817dependencies = [
812 "bincode",
813818 "crossbeam-channel",
814 "fnv",
815819 "libc",
816820 "mio",
821 "postcard",
817822 "rand 0.9.4",
818 "serde",
823 "rustc-hash 2.1.2",
824 "serde_core",
819825 "tempfile",
826 "thiserror 2.0.18",
820827 "uuid",
821828 "windows",
822829]
......@@ -982,7 +989,7 @@ dependencies = [
982989 "memmap2",
983990 "parking_lot",
984991 "perf-event-open-sys",
985 "rustc-hash",
992 "rustc-hash 1.1.0",
986993 "smallvec",
987994]
988995
......@@ -1192,6 +1199,18 @@ version = "1.13.1"
11921199source = "registry+https://github.com/rust-lang/crates.io-index"
11931200checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
11941201
1202[[package]]
1203name = "postcard"
1204version = "1.1.3"
1205source = "registry+https://github.com/rust-lang/crates.io-index"
1206checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
1207dependencies = [
1208 "cobs",
1209 "embedded-io 0.4.0",
1210 "embedded-io 0.6.1",
1211 "serde",
1212]
1213
11951214[[package]]
11961215name = "potential_utf"
11971216version = "0.1.5"
......@@ -1366,6 +1385,12 @@ version = "1.1.0"
13661385source = "registry+https://github.com/rust-lang/crates.io-index"
13671386checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
13681387
1388[[package]]
1389name = "rustc-hash"
1390version = "2.1.2"
1391source = "registry+https://github.com/rust-lang/crates.io-index"
1392checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
1393
13691394[[package]]
13701395name = "rustc_version"
13711396version = "0.4.1"
src/tools/miri/Cargo.toml+1-1
......@@ -38,7 +38,7 @@ serde = { version = "1.0.219", features = ["derive"], optional = true }
3838
3939[target.'cfg(target_os = "linux")'.dependencies]
4040nix = { version = "0.30.1", features = ["mman", "ptrace", "signal"], optional = true }
41ipc-channel = { version = "0.20.0", optional = true }
41ipc-channel = { version = "0.22.0", optional = true }
4242capstone = { version = "0.14", features = ["arch_x86", "full"], default-features = false, optional = true}
4343
4444[target.'cfg(all(target_os = "linux", target_pointer_width = "64", target_endian = "little"))'.dependencies]
src/tools/miri/cargo-miri/src/phases.rs+16-25
......@@ -342,7 +342,7 @@ pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) {
342342 .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
343343 let target_crate = is_target_crate();
344344
345 let store_json = |info: CrateRunInfo| {
345 let store_json = |info: &CrateRunInfo| {
346346 if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") {
347347 // Create a stub .d file to stop Cargo from "rebuilding" the crate:
348348 // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693
......@@ -383,9 +383,9 @@ pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) {
383383 // like we want them.
384384 // Instead of compiling, we write JSON into the output file with all the relevant command-line flags
385385 // and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
386 let env = CrateRunEnv::collect(args, inside_rustdoc);
386 let info = CrateRunInfo::collect(args, inside_rustdoc);
387387
388 store_json(CrateRunInfo::RunWith(env.clone()));
388 store_json(&info);
389389
390390 // Rustdoc expects us to exit with an error code if the test is marked as `compile_fail`,
391391 // 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<Item = String>, phase: RustcPhase) {
395395
396396 // Ensure --emit argument for a check-only build is present.
397397 if let Some(val) =
398 ArgFlagValueIter::from_str_iter(env.args.iter().map(|s| s as &str), "--emit").next()
398 ArgFlagValueIter::from_str_iter(info.args.iter().map(|s| s as &str), "--emit")
399 .next()
399400 {
400401 // For `no_run` tests, rustdoc passes a `--emit` flag; make sure it has the right shape.
401402 assert_eq!(val, "metadata");
......@@ -405,7 +406,7 @@ pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) {
405406 }
406407
407408 // Alter the `-o` parameter so that it does not overwrite the JSON file we stored above.
408 let mut args = env.args;
409 let mut args = info.args;
409410 for i in 0..args.len() {
410411 if args[i] == "-o" {
411412 args[i + 1].push_str(".miri");
......@@ -418,23 +419,22 @@ pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) {
418419 if verbose > 0 {
419420 eprintln!(
420421 "[cargo-miri rustc inside rustdoc] captured input:\n{}",
421 std::str::from_utf8(&env.stdin).unwrap()
422 std::str::from_utf8(&info.stdin).unwrap()
422423 );
423424 eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{cmd:?}");
424425 }
425426
426 exec_with_pipe(cmd, &env.stdin);
427 exec_with_pipe(cmd, &info.stdin);
427428 }
428429
429430 return;
430431 }
431432
433 // Unit tests for `proc-macro` crates are always built for the host so they cannot run in Miri.
432434 if runnable_crate && get_arg_flag_values("--extern").any(|krate| krate == "proc_macro") {
433 // This is a "runnable" `proc-macro` crate (unit tests). We do not support
434 // interpreting that under Miri now, so we write a JSON file to (display a
435 // helpful message and) skip it in the runner phase.
436 store_json(CrateRunInfo::SkipProcMacroTest);
437 return;
435 // Ideally we'd entirely skip them... but we have no good way of doing that here.
436 // So we run the tests natively on the host instead.
437 eprintln!("warning: unit tests of `proc-macro` crates are executed outside Miri");
438438 }
439439
440440 let mut cmd = miri();
......@@ -537,18 +537,9 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
537537 let file = BufReader::new(file);
538538 let binary_args = binary_args.collect::<Vec<_>>();
539539
540 let info = serde_json::from_reader(file).unwrap_or_else(|_| {
540 let info: CrateRunInfo = serde_json::from_reader(file).unwrap_or_else(|_| {
541541 show_error!("file {:?} contains outdated or invalid JSON; try `cargo clean`", binary)
542542 });
543 let info = match info {
544 CrateRunInfo::RunWith(info) => info,
545 CrateRunInfo::SkipProcMacroTest => {
546 eprintln!(
547 "Running unit tests of `proc-macro` crates is not currently supported by Miri."
548 );
549 return;
550 }
551 };
552543
553544 let mut cmd = miri();
554545
......@@ -631,10 +622,10 @@ pub fn phase_rustdoc(args: impl Iterator<Item = String>) {
631622 let mut cmd = Command::new(rustdoc);
632623 cmd.args(args);
633624
634 // Doctests of `proc-macro` crates (and their dependencies) are always built for the host,
635 // so we are not able to run them in Miri.
625 // Documentation tests of `proc-macro` crates are always built for the host, so we are not able
626 // to run them in Miri.
636627 if get_arg_flag_values("--crate-type").any(|crate_type| crate_type == "proc-macro") {
637 eprintln!("Running doctests of `proc-macro` crates is not currently supported by Miri.");
628 eprintln!("warning: doc tests of `proc-macro` crates are not supported by Miri");
638629 return;
639630 }
640631
src/tools/miri/cargo-miri/src/util.rs+5-16
......@@ -22,9 +22,9 @@ macro_rules! show_error {
2222}
2323pub(crate) use show_error;
2424
25/// The information to run a crate with the given environment.
26#[derive(Clone, Serialize, Deserialize)]
27pub struct CrateRunEnv {
25/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled".
26#[derive(Serialize, Deserialize)]
27pub struct CrateRunInfo {
2828 /// The command-line arguments.
2929 pub args: Vec<String>,
3030 /// The environment.
......@@ -35,7 +35,7 @@ pub struct CrateRunEnv {
3535 pub stdin: Vec<u8>,
3636}
3737
38impl CrateRunEnv {
38impl CrateRunInfo {
3939 /// Gather all the information we need.
4040 pub fn collect(args: impl Iterator<Item = String>, capture_stdin: bool) -> Self {
4141 let args = args.collect();
......@@ -47,20 +47,9 @@ impl CrateRunEnv {
4747 std::io::stdin().lock().read_to_end(&mut stdin).expect("cannot read stdin");
4848 }
4949
50 CrateRunEnv { args, env, current_dir, stdin }
50 CrateRunInfo { args, env, current_dir, stdin }
5151 }
52}
5352
54/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled".
55#[derive(Serialize, Deserialize)]
56pub enum CrateRunInfo {
57 /// Run it with the given environment.
58 RunWith(CrateRunEnv),
59 /// Skip it as Miri does not support interpreting such kind of crates.
60 SkipProcMacroTest,
61}
62
63impl CrateRunInfo {
6453 pub fn store(&self, filename: &Path) {
6554 let file = File::create(filename)
6655 .unwrap_or_else(|_| show_error!("cannot create `{}`", filename.display()));
src/tools/miri/priroda/Cargo.lock+46-21
......@@ -80,15 +80,6 @@ dependencies = [
8080 "windows-link 0.2.1",
8181]
8282
83[[package]]
84name = "bincode"
85version = "1.3.3"
86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
88dependencies = [
89 "serde",
90]
91
9283[[package]]
9384name = "bitflags"
9485version = "2.11.1"
......@@ -225,6 +216,15 @@ dependencies = [
225216 "inout",
226217]
227218
219[[package]]
220name = "cobs"
221version = "0.3.0"
222source = "registry+https://github.com/rust-lang/crates.io-index"
223checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
224dependencies = [
225 "thiserror 2.0.18",
226]
227
228228[[package]]
229229name = "color-eyre"
230230version = "0.6.5"
......@@ -339,6 +339,18 @@ dependencies = [
339339 "windows-sys",
340340]
341341
342[[package]]
343name = "embedded-io"
344version = "0.4.0"
345source = "registry+https://github.com/rust-lang/crates.io-index"
346checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
347
348[[package]]
349name = "embedded-io"
350version = "0.6.1"
351source = "registry+https://github.com/rust-lang/crates.io-index"
352checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
353
342354[[package]]
343355name = "encode_unicode"
344356version = "1.0.0"
......@@ -383,12 +395,6 @@ version = "0.1.9"
383395source = "registry+https://github.com/rust-lang/crates.io-index"
384396checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
385397
386[[package]]
387name = "fnv"
388version = "1.0.7"
389source = "registry+https://github.com/rust-lang/crates.io-index"
390checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
391
392398[[package]]
393399name = "foldhash"
394400version = "0.1.5"
......@@ -540,18 +546,19 @@ dependencies = [
540546
541547[[package]]
542548name = "ipc-channel"
543version = "0.20.2"
549version = "0.22.0"
544550source = "registry+https://github.com/rust-lang/crates.io-index"
545checksum = "f93600b5616c2d075f8af8dbd23c1d69278c5d24e4913d220cbc60b14c95c180"
551checksum = "347ef783e380784658248bdb0b87ca1293e3e3df3fc7dee061e129aa5f013d61"
546552dependencies = [
547 "bincode",
548553 "crossbeam-channel",
549 "fnv",
550554 "libc",
551555 "mio",
556 "postcard",
552557 "rand 0.9.4",
553 "serde",
558 "rustc-hash 2.1.2",
559 "serde_core",
554560 "tempfile",
561 "thiserror 2.0.18",
555562 "uuid",
556563 "windows",
557564]
......@@ -667,7 +674,7 @@ dependencies = [
667674 "memmap2",
668675 "parking_lot",
669676 "perf-event-open-sys",
670 "rustc-hash",
677 "rustc-hash 1.1.0",
671678 "smallvec",
672679]
673680
......@@ -840,6 +847,18 @@ version = "1.13.1"
840847source = "registry+https://github.com/rust-lang/crates.io-index"
841848checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
842849
850[[package]]
851name = "postcard"
852version = "1.1.3"
853source = "registry+https://github.com/rust-lang/crates.io-index"
854checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
855dependencies = [
856 "cobs",
857 "embedded-io 0.4.0",
858 "embedded-io 0.6.1",
859 "serde",
860]
861
843862[[package]]
844863name = "ppv-lite86"
845864version = "0.2.21"
......@@ -1014,6 +1033,12 @@ version = "1.1.0"
10141033source = "registry+https://github.com/rust-lang/crates.io-index"
10151034checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
10161035
1036[[package]]
1037name = "rustc-hash"
1038version = "2.1.2"
1039source = "registry+https://github.com/rust-lang/crates.io-index"
1040checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
1041
10171042[[package]]
10181043name = "rustc_version"
10191044version = "0.4.1"
src/tools/miri/priroda/README.md+4-1
......@@ -8,6 +8,7 @@ Current focus:
88- single-threaded stepping with Miri's interpreter
99- source-location output after stepping
1010- source-location breakpoint prototype
11- source-local listing prototype
1112
1213## Setup
1314
......@@ -59,9 +60,11 @@ RUSTC_BLESS=1 cargo test
5960
6061| Command | Description |
6162|---|---|
62| Enter, `s`, `step` | Execute one Miri interpreter step. |
63| Enter, `si`, `stepi` | Execute one Miri interpreter step. |
64| `s`, `step` | Step until the displayed source location changes. |
6365| `c`, `continue` | Continue until the program finishes or reaches a breakpoint. |
6466| `b <path>:<line>`, `break <path>:<line>` | Add a source-location breakpoint. |
67| `l`, `locals` | List source-level locals in the current frame by name. |
6568| `q`, `quit` | Exit Priroda. |
6669
6770EOF also exits Priroda cleanly.
src/tools/miri/priroda/src/main.rs+91-20
......@@ -71,7 +71,7 @@ impl rustc_driver::Callbacks for PrirodaCompilerCalls {
7171 let ecx = create_ecx(tcx);
7272
7373 let mut session = PrirodaContext::new(ecx);
74 let cli = CLI {};
74 let cli = Cli {};
7575 let result = cli.run_cli_loop(&mut session);
7676
7777 match result.report_err() {
......@@ -133,6 +133,10 @@ struct PrirodaContext<'tcx> {
133133enum ResumeMode {
134134 /// Stop at the next visible MIR instruction.
135135 MirInstruction,
136 /// Stop at the next source line
137 ///
138 /// Take `Option` because some cases current state has no mapped to source code location
139 SourceLine(Option<(PathBuf, usize)>),
136140 /// Continue until reaching a breakpoint.
137141 Continue,
138142}
......@@ -159,10 +163,31 @@ impl<'tcx> PrirodaContext<'tcx> {
159163 Self { ecx, breakpoints: HashMap::new(), current_location: None, last_location: None }
160164 }
161165
166 fn local_path(&self, location: &SourceLocation) -> Option<PathBuf> {
167 let source_map = self.ecx.tcx.sess.source_map();
168 location.local_path(source_map)
169 }
170
171 fn current_source_position(&self) -> Option<(PathBuf, usize)> {
172 let location = self.current_location.as_ref()?;
173 Some((self.local_path(location)?, location.line))
174 }
175
176 // Used to treat `continue` like a source-level step for breakpoint checks:
177 // several MIR locations can point at one source line, but they should only
178 // report that source breakpoint once.
179 fn last_source_position(&self) -> Option<(PathBuf, usize)> {
180 let location = self.last_location.as_ref()?;
181 Some((self.local_path(location)?, location.line))
182 }
183
162184 /// Step to the next visible MIR instruction.
163 fn step(&mut self) -> InterpResult<'tcx, StepResult> {
185 fn stepi(&mut self) -> InterpResult<'tcx, StepResult> {
164186 self.resume(ResumeMode::MirInstruction)
165187 }
188 fn step(&mut self) -> InterpResult<'tcx, StepResult> {
189 self.resume(ResumeMode::SourceLine(self.current_source_position()))
190 }
166191
167192 /// Continue execution until reaching a breakpoint or propagating termination.
168193 fn continue_execution(&mut self) -> InterpResult<'tcx, StepResult> {
......@@ -202,6 +227,26 @@ impl<'tcx> PrirodaContext<'tcx> {
202227 {
203228 return interp_ok(StepResult::Step);
204229 }
230
231 ResumeMode::SourceLine(ref prev_location) => {
232 match (prev_location, &self.current_location) {
233 // We started from an unmapped source location. Stop at the first mapped source location we can show to the user.
234 (None, Some(_)) => return interp_ok(StepResult::Step),
235
236 (Some((prev_path, prev_line)), Some(current_location)) => {
237 if let Some(current_path) = self.local_path(current_location) {
238 // A source step stops when the visible source position changes to a different file or line.
239 if *prev_path != current_path || *prev_line != current_location.line
240 {
241 return interp_ok(StepResult::Step);
242 }
243 }
244 }
245
246 _ => {}
247 }
248 }
249
205250 ResumeMode::MirInstruction | ResumeMode::Continue => {}
206251 }
207252 }
......@@ -248,21 +293,20 @@ impl<'tcx> PrirodaContext<'tcx> {
248293 }
249294
250295 fn is_at_breakpoint(&self) -> bool {
251 // FIXME: avoid repeated stops when one source line maps to multiple MIR statements.
252 let Some(location) = &self.current_location else {
296 let Some(bp) = self.current_breakpoint() else {
253297 return false;
254298 };
255299
256 let source_map = self.ecx.tcx.sess.source_map();
257 let Some(path) = &location.local_path(source_map) else {
258 return false;
259 };
300 // If the previous interpreter step had the same source position, this
301 // is another MIR location for the breakpoint we just reported.
302 self.last_source_position().as_ref() != Some(&bp)
303 }
260304
261 let lines = match self.breakpoints.get(path) {
262 Some(lines) => lines,
263 None => return false,
264 };
265 lines.contains(&location.line)
305 fn current_breakpoint(&self) -> Option<(PathBuf, usize)> {
306 let (path, line) = self.current_source_position()?;
307 let lines = self.breakpoints.get(&path)?;
308
309 if lines.contains(&line) { Some((path, line)) } else { None }
266310 }
267311
268312 fn resolve_current_location(&self) -> Option<SourceLocation> {
......@@ -276,26 +320,41 @@ impl<'tcx> PrirodaContext<'tcx> {
276320 let source_map = self.ecx.tcx.sess.source_map();
277321 let loc = source_map.lookup_char_pos(span.lo());
278322
279 Some(SourceLocation { span: span, line: loc.line })
323 Some(SourceLocation { span, line: loc.line })
280324 }
281325
282326 fn run_command(&mut self, command: DebuggerCommand) -> InterpResult<'tcx, CommandResult> {
283327 match command {
328 DebuggerCommand::StepI => self.stepi().map(CommandResult::ExecutionStopped),
284329 DebuggerCommand::Step => self.step().map(CommandResult::ExecutionStopped),
285330 DebuggerCommand::Continue =>
286331 self.continue_execution().map(CommandResult::ExecutionStopped),
287332 DebuggerCommand::Breakpoint(path, line) =>
288333 interp_ok(CommandResult::BreakpointResult(self.set_breakpoint(path, line))),
334 DebuggerCommand::ListLocals => interp_ok(CommandResult::Locals(self.list_locals())),
289335 DebuggerCommand::TerminateSession => interp_ok(CommandResult::TerminateSession),
290336 }
291337 }
338
339 /// Returns the names of all user-visible locals in the innermost stack frame.
340 ///
341 /// Uses `var_debug_info` from the MIR body, which is the same source that
342 /// DWARF debug info is built from, so the names match what the user wrote.
343 fn list_locals(&self) -> Vec<String> {
344 let Some(frame) = self.ecx.active_thread_stack().last() else {
345 return Vec::new();
346 };
347 frame.body().var_debug_info.iter().map(|info| info.name.to_string()).collect()
348 }
292349}
293350
294351enum DebuggerCommand {
352 StepI,
295353 Step,
296354 TerminateSession,
297355 Continue,
298356 Breakpoint(PathBuf, usize),
357 ListLocals,
299358}
300359
301360enum BreakpointSetResult {
......@@ -307,14 +366,15 @@ enum BreakpointSetResult {
307366enum CommandResult {
308367 ExecutionStopped(StepResult),
309368 BreakpointResult(BreakpointSetResult),
369 Locals(Vec<String>),
310370 // FIXME: distinguish terminating the debugger session from disconnecting a
311371 // frontend and terminating the interpreted program once multiple frontends exist.
312372 TerminateSession,
313373}
314374
315struct CLI;
375struct Cli;
316376
317impl CLI {
377impl Cli {
318378 pub fn run_cli_loop<'tcx>(&self, session: &mut PrirodaContext<'tcx>) -> InterpResult<'tcx> {
319379 loop {
320380 print!("(priroda) ");
......@@ -334,7 +394,7 @@ impl CLI {
334394 if matches!(result, StepResult::Breakpoint) {
335395 println!("Hit breakpoint");
336396 }
337 self.print_location(&session);
397 self.print_location(session);
338398 }
339399 CommandResult::BreakpointResult(res) =>
340400 match res {
......@@ -343,6 +403,14 @@ impl CLI {
343403
344404 BreakpointSetResult::Duplicate => println!("Duplicate breakpoint"),
345405 },
406 CommandResult::Locals(names) =>
407 if names.is_empty() {
408 println!("no locals");
409 } else {
410 for name in &names {
411 println!("{name}");
412 }
413 },
346414 CommandResult::TerminateSession => {
347415 println!("quitting");
348416 return interp_ok(());
......@@ -367,21 +435,24 @@ impl CLI {
367435 let args = parts.next().unwrap_or("").trim();
368436
369437 match command {
370 "" | "s" | "step" => Some(DebuggerCommand::Step),
438 // FIXME: empty line should repats last command user typed not exeute specific command.
439 "" | "si" | "stepi" => Some(DebuggerCommand::StepI),
440 "s" | "step" => Some(DebuggerCommand::Step),
371441 "q" | "quit" => Some(DebuggerCommand::TerminateSession),
372442 "c" | "continue" => Some(DebuggerCommand::Continue),
373443 "b" | "break" => self.parse_breakpoint(args),
444 "l" | "locals" => Some(DebuggerCommand::ListLocals),
374445 _ => None,
375446 }
376447 }
377448
378449 fn print_location(&self, session: &PrirodaContext) {
379 let source_map = session.ecx.tcx.sess.source_map();
380450 match &session.current_location {
381451 Some(location) =>
382 if let Some(path) = location.local_path(source_map) {
452 if let Some(path) = session.local_path(location) {
383453 println!("{}:{}", path.display(), location.line);
384454 } else {
455 let source_map = session.ecx.tcx.sess.source_map();
385456 println!("{}", source_map.span_to_diagnostic_string(location.span));
386457 },
387458 None => println!("no-location"),
src/tools/miri/priroda/tests/ui/locals_in_function.rs created+7
......@@ -0,0 +1,7 @@
1// Verifies that the `locals` command lists the names of user-declared variables
2// in the current stack frame. After stepping into `main` we should see `x` and `y`.
3fn main() {
4 let x = 1_i32;
5 let y = true;
6 let _ = (x, y);
7}
src/tools/miri/priroda/tests/ui/locals_in_function.stdin created+4
......@@ -0,0 +1,4 @@
1break tests/ui/locals_in_function.rs:5
2continue
3locals
4quit
src/tools/miri/priroda/tests/ui/locals_in_function.stdout created+6
......@@ -0,0 +1,6 @@
1(priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5
2(priroda) Hit breakpoint
3{MANIFEST_DIR}/tests/ui/locals_in_function.rs:5
4(priroda) x
5y
6(priroda) quitting
src/tools/miri/priroda/tests/ui/locals_no_frame.rs created+4
......@@ -0,0 +1,4 @@
1// Verifies that the `locals` command reports "no locals" when invoked before
2// any user stack frame is active (i.e. immediately at startup, while the std
3// runtime preamble is running).
4fn main() {}
src/tools/miri/priroda/tests/ui/locals_no_frame.stdin created+2
......@@ -0,0 +1,2 @@
1locals
2quit
src/tools/miri/priroda/tests/ui/locals_no_frame.stdout created+2
......@@ -0,0 +1,2 @@
1(priroda) no locals
2(priroda) quitting
src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.rs+6-5
......@@ -1,7 +1,8 @@
1// Documents the current repeated-stop behavior when multiple MIR locations map
2// to the same source breakpoint line.
3// This may look trivial, but a bunch of code runs in std before
4// `main` is called, so we are ensuring that that all works.
1// Verifies duplicate MIR locations on one source breakpoint line are skipped.
2// The following line gives the second `continue` a later real breakpoint.
3// This keeps the test from passing merely because the program finished.
4// Keep the breakpoint line numbers in the .stdin file in sync with this file.
55fn main() {
6 let _value = 0;
6 let _first = 0;
7 let _second = 1;
78}
src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdin+1
......@@ -1,4 +1,5 @@
11break tests/ui/repeated_same_line_breakpoint.rs:6
2break tests/ui/repeated_same_line_breakpoint.rs:7
23continue
34continue
45quit
src/tools/miri/priroda/tests/ui/repeated_same_line_breakpoint.stdout+2-1
......@@ -1,6 +1,7 @@
11(priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6
2(priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:7
23(priroda) Hit breakpoint
34{MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6
45(priroda) Hit breakpoint
5{MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:6
6{MANIFEST_DIR}/tests/ui/repeated_same_line_breakpoint.rs:7
67(priroda) quitting
src/tools/miri/priroda/tests/ui/source_step_changes_line.stdin+1-1
......@@ -1,3 +1,3 @@
1si
12s
2step
33quit
src/tools/miri/priroda/tests/ui/source_step_changes_line.stdout+1-1
......@@ -1,3 +1,3 @@
11(priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:206
2(priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:206
2(priroda) {RUSTC_SYSROOT}/lib/rustlib/src/rust/library/std/src/rt.rs:207
33(priroda) quitting
src/tools/miri/priroda/tests/ui/step_aliases.stdin+2-2
......@@ -1,4 +1,4 @@
1s
2step
1si
2stepi
33
44quit
src/tools/miri/rust-version+1-1
......@@ -1 +1 @@
1029c9e18dd1f4668e1d42bb187c1c263dfe20093
101f54e80e888b66d6486a3a95d481b87353016df
src/tools/miri/src/shims/native_lib/trace/child.rs+3-3
......@@ -2,7 +2,7 @@ use std::cell::RefCell;
22use std::ptr::NonNull;
33use std::rc::Rc;
44
5use ipc_channel::ipc;
5use ipc_channel::{TryRecvError, ipc};
66use nix::sys::{mman, ptrace, signal};
77use nix::unistd;
88use rustc_const_eval::interpret::{InterpResult, interp_ok};
......@@ -140,8 +140,8 @@ impl Supervisor {
140140 .try_recv_timeout(std::time::Duration::from_secs(5))
141141 .map_err(|e| {
142142 match e {
143 ipc::TryRecvError::IpcError(_) => (),
144 ipc::TryRecvError::Empty =>
143 TryRecvError::IpcError(_) => (),
144 TryRecvError::Empty =>
145145 panic!("Waiting for accesses from supervisor timed out!"),
146146 }
147147 })
src/tools/miri/test-cargo-miri/run-test.py+1-1
......@@ -172,7 +172,7 @@ def test_cargo_miri_test():
172172 )
173173 test("`cargo miri test` (proc-macro crate)",
174174 cargo_miri("test") + ["-p", "proc_macro_crate"],
175 "test.empty.ref", "test.proc-macro.stderr.ref",
175 "test.proc-macro.stdout.ref", "test.proc-macro.stderr.ref",
176176 )
177177 test("`cargo miri test` (custom target dir)",
178178 cargo_miri("test") + ["--target-dir=custom-test"],
src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref+2-2
......@@ -1,2 +1,2 @@
1Running unit tests of `proc-macro` crates is not currently supported by Miri.
2Running doctests of `proc-macro` crates is not currently supported by Miri.
1warning: unit tests of `proc-macro` crates are executed outside Miri
2warning: doc tests of `proc-macro` crates are not supported by Miri
src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref created+5
......@@ -0,0 +1,5 @@
1
2running 0 tests
3
4test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
5
src/tools/miri/tests/pass/both_borrows/c_variadics.rs+4-5
......@@ -4,14 +4,13 @@
44#![feature(c_variadic)]
55
66fn main() {
7 unsafe extern "C" fn write_with_first_arg(
8 ptr_to_val: *mut i32,
9 _hidden_mut_ref_to_val: ...
10 ) {
7 unsafe extern "C" fn write_with_first_arg(ptr_to_val: *mut i32, _hidden_mut_ref_to_val: ...) {
118 // Retagging needs to be disabled for arguments
129 // within the VaList. Otherwise, this write access
1310 // will be undefined behavior.
14 unsafe { *ptr_to_val = 32; }
11 unsafe {
12 *ptr_to_val = 32;
13 }
1514 }
1615
1716 let mut val: i32 = 0;
src/tools/miri/tests/pass/tree_borrows/slice_get_mut_no_implicit_write.rs+1-3
......@@ -24,9 +24,7 @@ fn borrowed_buf() {
2424
2525 let ptr = unsafe { buf.as_mut() }.as_mut_ptr();
2626 let _ = buf.capacity();
27 unsafe {
28 ptr.write(42);
29 }
27 unsafe { ptr.write(42) };
3028}
3129
3230// A variant of the above that uses `index_mut` notation.
src/tools/rust-analyzer/Cargo.lock+1-33
......@@ -90,7 +90,7 @@ dependencies = [
9090 "cfg-if",
9191 "libc",
9292 "miniz_oxide",
93 "object 0.37.3",
93 "object",
9494 "rustc-demangle",
9595 "windows-link",
9696]
......@@ -1416,16 +1416,6 @@ version = "0.2.186"
14161416source = "registry+https://github.com/rust-lang/crates.io-index"
14171417checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
14181418
1419[[package]]
1420name = "libloading"
1421version = "0.8.9"
1422source = "registry+https://github.com/rust-lang/crates.io-index"
1423checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
1424dependencies = [
1425 "cfg-if",
1426 "windows-link",
1427]
1428
14291419[[package]]
14301420name = "libmimalloc-sys"
14311421version = "0.1.49"
......@@ -1589,15 +1579,6 @@ version = "2.8.1"
15891579source = "registry+https://github.com/rust-lang/crates.io-index"
15901580checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
15911581
1592[[package]]
1593name = "memmap2"
1594version = "0.9.10"
1595source = "registry+https://github.com/rust-lang/crates.io-index"
1596checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
1597dependencies = [
1598 "libc",
1599]
1600
16011582[[package]]
16021583name = "memoffset"
16031584version = "0.9.1"
......@@ -1756,15 +1737,6 @@ version = "4.1.0"
17561737source = "registry+https://github.com/rust-lang/crates.io-index"
17571738checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
17581739
1759[[package]]
1760name = "object"
1761version = "0.36.7"
1762source = "registry+https://github.com/rust-lang/crates.io-index"
1763checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
1764dependencies = [
1765 "memchr",
1766]
1767
17681740[[package]]
17691741name = "object"
17701742version = "0.37.3"
......@@ -1992,11 +1964,7 @@ version = "0.0.0"
19921964dependencies = [
19931965 "expect-test",
19941966 "intern",
1995 "libc",
1996 "libloading",
19971967 "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1998 "memmap2",
1999 "object 0.36.7",
20001968 "paths",
20011969 "proc-macro-test",
20021970 "span",
src/tools/rust-analyzer/Cargo.toml-9
......@@ -116,17 +116,8 @@ expect-test = "1.5.1"
116116indexmap = { version = "2.9.0", features = ["serde"] }
117117itertools = "0.14.0"
118118libc = "0.2.172"
119libloading = "0.8.8"
120memmap2 = "0.9.5"
121119nohash-hasher = "0.2.0"
122120oorandom = "11.1.5"
123object = { version = "0.36.7", default-features = false, features = [
124 "std",
125 "read_core",
126 "elf",
127 "macho",
128 "pe",
129] }
130121postcard = { version = "1.1.3", features = ["alloc"] }
131122process-wrap = { version = "9.1.0", features = ["std"] }
132123pulldown-cmark-to-cmark = "10.0.4"
src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml-6
......@@ -13,9 +13,6 @@ rust-version.workspace = true
1313doctest = false
1414
1515[dependencies]
16object.workspace = true
17libloading.workspace = true
18memmap2.workspace = true
1916temp-dir.workspace = true
2017
2118paths.workspace = true
......@@ -24,9 +21,6 @@ span = { path = "../span", version = "0.0.0", default-features = false}
2421intern.workspace = true
2522
2623
27[target.'cfg(unix)'.dependencies]
28libc.workspace = true
29
3024[dev-dependencies]
3125expect-test.workspace = true
3226line-index.workspace = true
src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs+7-162
......@@ -4,22 +4,18 @@ mod proc_macros;
44
55use rustc_codegen_ssa::back::metadata::DefaultMetadataLoader;
66use rustc_interface::util::rustc_version_str;
7use rustc_metadata::locator::MetadataError;
87use rustc_proc_macro::bridge;
98use rustc_session::config::host_tuple;
109use rustc_target::spec::{Target, TargetTuple};
1110use std::path::Path;
12use std::{fmt, fs, io, time::SystemTime};
11use std::{fs, io, time::SystemTime};
1312use temp_dir::TempDir;
1413
15use libloading::Library;
16use object::Object;
1714use paths::{Utf8Path, Utf8PathBuf};
1815
1916use crate::{
2017 PanicMessage, ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, TrackedEnv,
21 dylib::proc_macros::{ProcMacroClients, ProcMacros},
22 token_stream::TokenStream,
18 dylib::proc_macros::ProcMacros, token_stream::TokenStream,
2319};
2420
2521pub(crate) struct Expander {
......@@ -28,10 +24,7 @@ pub(crate) struct Expander {
2824}
2925
3026impl Expander {
31 pub(crate) fn new(
32 temp_dir: &TempDir,
33 lib: &Utf8Path,
34 ) -> Result<Expander, LoadProcMacroDylibError> {
27 pub(crate) fn new(temp_dir: &TempDir, lib: &Utf8Path) -> io::Result<Expander> {
3528 // Some libraries for dynamic loading require canonicalized path even when it is
3629 // already absolute
3730 let lib = lib.canonicalize_utf8()?;
......@@ -78,61 +71,17 @@ impl Expander {
7871 }
7972}
8073
81#[derive(Debug)]
82pub enum LoadProcMacroDylibError {
83 Io(io::Error),
84 LibLoading(libloading::Error),
85 MetadataError(MetadataError<'static>),
86}
87
88impl fmt::Display for LoadProcMacroDylibError {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 match self {
91 Self::Io(e) => e.fmt(f),
92 Self::LibLoading(e) => e.fmt(f),
93 Self::MetadataError(e) => e.fmt(f),
94 }
95 }
96}
97
98impl From<io::Error> for LoadProcMacroDylibError {
99 fn from(e: io::Error) -> Self {
100 LoadProcMacroDylibError::Io(e)
101 }
102}
103
104impl From<libloading::Error> for LoadProcMacroDylibError {
105 fn from(e: libloading::Error) -> Self {
106 LoadProcMacroDylibError::LibLoading(e)
107 }
108}
109
110impl From<MetadataError<'_>> for LoadProcMacroDylibError {
111 fn from(e: MetadataError<'_>) -> Self {
112 LoadProcMacroDylibError::MetadataError(match e {
113 MetadataError::NotPresent(path) => MetadataError::NotPresent(path.into_owned().into()),
114 MetadataError::LoadFailure(err) => MetadataError::LoadFailure(err),
115 MetadataError::VersionMismatch { expected_version, found_version } => {
116 MetadataError::VersionMismatch { expected_version, found_version }
117 }
118 })
119 }
120}
121
12274struct ProcMacroLibrary {
123 // this contains references to the library, so make sure this drops before _lib
12475 proc_macros: ProcMacros,
125 // Hold on to the library so it doesn't unload
126 _lib: Library,
12776}
12877
12978impl ProcMacroLibrary {
130 fn open(path: &Utf8Path) -> Result<Self, LoadProcMacroDylibError> {
131 let proc_macro_kinds = rustc_span::create_default_session_globals_then(|| {
79 fn open(path: &Utf8Path) -> io::Result<Self> {
80 let proc_macros = rustc_span::create_default_session_globals_then(|| {
13281 let (target, _) =
13382 Target::search(&TargetTuple::from_tuple(host_tuple()), Path::new(""), false)
13483 .unwrap();
135 rustc_metadata::locator::get_proc_macro_info(
84 rustc_metadata::locator::get_proc_macros(
13685 &target,
13786 path.as_ref(),
13887 &DefaultMetadataLoader,
......@@ -140,63 +89,10 @@ impl ProcMacroLibrary {
14089 )
14190 })?;
14291
143 let file = fs::File::open(path)?;
144 #[allow(clippy::undocumented_unsafe_blocks)] // FIXME
145 let file = unsafe { memmap2::Mmap::map(&file) }?;
146 let obj = object::File::parse(&*file)
147 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
148 let symbol_name =
149 find_registrar_symbol(&obj).map_err(invalid_data_err)?.ok_or_else(|| {
150 invalid_data_err(format!("Cannot find registrar symbol in file {path}"))
151 })?;
152
153 // SAFETY: We have verified the validity of the dylib as a proc-macro library
154 let lib = unsafe { load_library(path) }.map_err(invalid_data_err)?;
155 // SAFETY: We have verified the validity of the dylib as a proc-macro library
156 // The 'static lifetime is a lie, it's actually the lifetime of the library but unavoidable
157 // due to self-referentiality
158 // But we make sure that we do not drop it before the symbol is dropped
159 let proc_macros =
160 unsafe { lib.get::<&'static &'static ProcMacroClients>(symbol_name.as_bytes()) };
161 match proc_macros {
162 Ok(proc_macros) => Ok(ProcMacroLibrary {
163 proc_macros: ProcMacros::new(*proc_macros, proc_macro_kinds),
164 _lib: lib,
165 }),
166 Err(e) => Err(e.into()),
167 }
92 Ok(ProcMacroLibrary { proc_macros: ProcMacros::new(proc_macros) })
16893 }
16994}
17095
171fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
172 io::Error::new(io::ErrorKind::InvalidData, e)
173}
174
175fn is_derive_registrar_symbol(symbol: &str) -> bool {
176 const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
177 symbol.contains(NEW_REGISTRAR_SYMBOL)
178}
179
180fn find_registrar_symbol(obj: &object::File<'_>) -> object::Result<Option<String>> {
181 Ok(obj
182 .exports()?
183 .into_iter()
184 .map(|export| export.name())
185 .filter_map(|sym| String::from_utf8(sym.into()).ok())
186 .find(|sym| is_derive_registrar_symbol(sym))
187 .map(|sym| {
188 // From MacOS docs:
189 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
190 // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
191 // prepended with an underscore.
192 if cfg!(target_os = "macos") && sym.starts_with('_') {
193 sym[1..].to_owned()
194 } else {
195 sym
196 }
197 }))
198}
199
20096/// Copy the dylib to temp directory to prevent locking in Windows
20197#[cfg(windows)]
20298fn ensure_file_with_lock_free_access(
......@@ -233,54 +129,3 @@ fn ensure_file_with_lock_free_access(
233129) -> io::Result<Utf8PathBuf> {
234130 Ok(path.to_owned())
235131}
236
237/// Loads dynamic library in platform dependent manner.
238///
239/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
240/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
241/// and [here](https://github.com/rust-lang/rust/issues/60593).
242///
243/// Usage of RTLD_DEEPBIND
244/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
245///
246/// It seems that on Windows that behaviour is default, so we do nothing in that case.
247///
248/// # Safety
249///
250/// The caller is responsible for ensuring that the path is valid proc-macro library
251#[cfg(windows)]
252unsafe fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
253 // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
254 unsafe { Library::new(file) }
255}
256
257/// Loads dynamic library in platform dependent manner.
258///
259/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
260/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
261/// and [here](https://github.com/rust-lang/rust/issues/60593).
262///
263/// Usage of RTLD_DEEPBIND
264/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
265///
266/// It seems that on Windows that behaviour is default, so we do nothing in that case.
267///
268/// # Safety
269///
270/// The caller is responsible for ensuring that the path is valid proc-macro library
271#[cfg(unix)]
272unsafe fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
273 // not defined by POSIX, different values on mips vs other targets
274 #[cfg(target_env = "gnu")]
275 use libc::RTLD_DEEPBIND;
276 use libloading::os::unix::Library as UnixLibrary;
277 // defined by POSIX
278 use libloading::os::unix::RTLD_NOW;
279
280 // MUSL and bionic don't have it..
281 #[cfg(not(target_env = "gnu"))]
282 const RTLD_DEEPBIND: std::os::raw::c_int = 0x0;
283
284 // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
285 unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) }
286}
src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs+2-6
......@@ -4,9 +4,6 @@ use crate::{
44};
55use rustc_proc_macro::bridge;
66
7#[repr(transparent)]
8pub(crate) struct ProcMacroClients([bridge::client::Client]);
9
107impl From<bridge::PanicMessage> for crate::PanicMessage {
118 fn from(p: bridge::PanicMessage) -> Self {
129 Self { message: p.into_string() }
......@@ -17,10 +14,9 @@ pub(crate) struct ProcMacros(Vec<(bridge::client::Client, rustc_metadata::ProcMa
1714
1815impl ProcMacros {
1916 pub(super) fn new(
20 clients: &ProcMacroClients,
21 kinds: Vec<rustc_metadata::ProcMacroKind>,
17 macros: Vec<(bridge::client::Client, rustc_metadata::ProcMacroKind)>,
2218 ) -> Self {
23 ProcMacros(clients.0.iter().copied().zip(kinds).collect::<Vec<_>>())
19 ProcMacros(macros)
2420 }
2521
2622 pub(crate) fn expand<'a, S: ProcMacroSrvSpan>(
src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs+2-1
......@@ -10,9 +10,10 @@
1010
1111#![cfg(feature = "in-rust-tree")]
1212#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)]
13#![expect(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)]
13#![expect(internal_features, clippy::disallowed_types, clippy::print_stderr)]
1414#![allow(unused_features, unused_crate_dependencies)]
1515#![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)]
16#![cfg_attr(test, expect(unreachable_pub))]
1617
1718extern crate rustc_codegen_ssa;
1819extern crate rustc_driver as _;
tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff created+27
......@@ -0,0 +1,27 @@
1- // MIR for `dont_remove_moved_comparison` before SimplifyComparisonIntegral
2+ // MIR for `dont_remove_moved_comparison` after SimplifyComparisonIntegral
3
4 fn dont_remove_moved_comparison(_1: i8) -> i32 {
5 let mut _0: i32;
6 let mut _2: bool;
7 let mut _3: i32;
8 let mut _4: i32;
9
10 bb0: {
11 _2 = Eq(copy _1, const 17_i8);
12 _3 = copy _2 as i32 (IntToInt);
13- switchInt(move _2) -> [1: bb1, otherwise: bb2];
14+ switchInt(copy _1) -> [17: bb1, otherwise: bb2];
15 }
16
17 bb1: {
18 _0 = copy _3;
19 return;
20 }
21
22 bb2: {
23 _0 = Add(copy _3, const 1_i32);
24 return;
25 }
26 }
27
tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff+1-2
......@@ -11,9 +11,8 @@
1111 StorageLive(_2);
1212 StorageLive(_3);
1313 _3 = copy _1;
14- _2 = Eq(copy _1, const 'x');
14 _2 = Eq(copy _1, const 'x');
1515- switchInt(move _2) -> [0: bb2, otherwise: bb1];
16+ nop;
1716+ switchInt(copy _1) -> [120: bb1, otherwise: bb2];
1817 }
1918
tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff+1-2
......@@ -11,9 +11,8 @@
1111 StorageLive(_2);
1212 StorageLive(_3);
1313 _3 = copy _1;
14- _2 = Eq(copy _1, const 42_i8);
14 _2 = Eq(copy _1, const 42_i8);
1515- switchInt(move _2) -> [0: bb2, otherwise: bb1];
16+ nop;
1716+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
1817 }
1918
tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff+2-4
......@@ -13,9 +13,8 @@
1313 StorageLive(_2);
1414 StorageLive(_3);
1515 _3 = copy _1;
16- _2 = Eq(copy _1, const 42_u32);
16 _2 = Eq(copy _1, const 42_u32);
1717- switchInt(move _2) -> [0: bb2, otherwise: bb1];
18+ nop;
1918+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
2019 }
2120
......@@ -30,9 +29,8 @@
3029 StorageLive(_4);
3130 StorageLive(_5);
3231 _5 = copy _1;
33- _4 = Ne(copy _1, const 21_u32);
32 _4 = Ne(copy _1, const 21_u32);
3433- switchInt(move _4) -> [0: bb4, otherwise: bb3];
35+ nop;
3634+ switchInt(copy _1) -> [21: bb4, otherwise: bb3];
3735 }
3836
tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff+1-2
......@@ -11,9 +11,8 @@
1111 StorageLive(_2);
1212 StorageLive(_3);
1313 _3 = copy _1;
14- _2 = Eq(copy _1, const -42_i32);
14 _2 = Eq(copy _1, const -42_i32);
1515- switchInt(move _2) -> [0: bb2, otherwise: bb1];
16+ nop;
1716+ switchInt(copy _1) -> [4294967254: bb1, otherwise: bb2];
1817 }
1918
tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff+1-2
......@@ -11,9 +11,8 @@
1111 StorageLive(_2);
1212 StorageLive(_3);
1313 _3 = copy _1;
14- _2 = Eq(copy _1, const 42_u32);
14 _2 = Eq(copy _1, const 42_u32);
1515- switchInt(move _2) -> [0: bb2, otherwise: bb1];
16+ nop;
1716+ switchInt(copy _1) -> [42: bb1, otherwise: bb2];
1817 }
1918
tests/mir-opt/if_condition_int.rs+37-1
......@@ -85,7 +85,7 @@ fn opt_multiple_ifs(x: u32) -> u32 {
8585}
8686
8787// EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
88// test that we optimize, but do not remove the b statement, as that is used later on
88// the switchInt can be optimized but the b statement can't be removed as it's used later on
8989fn dont_remove_comparison(a: i8) -> i32 {
9090 // CHECK-LABEL: fn dont_remove_comparison(
9191 // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8);
......@@ -103,6 +103,42 @@ fn dont_remove_comparison(a: i8) -> i32 {
103103 }
104104}
105105
106// EMIT_MIR if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff
107// like dont_remove_comparison above, but with switchInt(move _N) - regression test for #158206
108#[custom_mir(dialect = "runtime")]
109fn dont_remove_moved_comparison(a: i8) -> i32 {
110 // CHECK-LABEL: fn dont_remove_moved_comparison(
111 // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8);
112 // CHECK: [[cast:_.*]] = copy [[b]] as i32 (IntToInt);
113 // CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]];
114 // CHECK: [[BB1]]:
115 // CHECK: _0 = copy [[cast]];
116 // CHECK: [[BB2]]:
117 // CHECK: _0 = Add(copy [[cast]], const 1_i32);
118 mir! {
119 let b: bool;
120 let c: i32;
121 let d: i32;
122 {
123 b = a == 17;
124 c = b as i32;
125 match Move(b) {
126 true => bb1,
127 _ => bb2,
128 }
129
130 }
131 bb1 = {
132 RET = c;
133 Return()
134 }
135 bb2 = {
136 RET = c + 1;
137 Return()
138 }
139 }
140}
141
106142// EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
107143// test that we do not optimize on floats
108144fn dont_opt_floats(a: f32) -> i32 {
tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr+26-36
......@@ -1,85 +1,75 @@
1warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
1warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on constants
22 --> $DIR/incorrect-locations.rs:7:1
33 |
44LL | #[diagnostic::do_not_recommend]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6LL |
7LL | const CONST: () = ();
8 | --------------------- not a trait implementation
96 |
7 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
108 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
119
12warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
10warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on statics
1311 --> $DIR/incorrect-locations.rs:11:1
1412 |
1513LL | #[diagnostic::do_not_recommend]
1614 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17LL |
18LL | static STATIC: () = ();
19 | ----------------------- not a trait implementation
15 |
16 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
2017
21warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
18warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on type aliases
2219 --> $DIR/incorrect-locations.rs:15:1
2320 |
2421LL | #[diagnostic::do_not_recommend]
2522 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26LL |
27LL | type Type = ();
28 | --------------- not a trait implementation
23 |
24 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
2925
30warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
26warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on enums
3127 --> $DIR/incorrect-locations.rs:19:1
3228 |
3329LL | #[diagnostic::do_not_recommend]
3430 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35LL |
36LL | enum Enum {}
37 | ------------ not a trait implementation
31 |
32 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
3833
39warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
34warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on inherent impl blocks
4035 --> $DIR/incorrect-locations.rs:23:1
4136 |
4237LL | #[diagnostic::do_not_recommend]
4338 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44LL |
45LL | impl Enum {}
46 | ------------ not a trait implementation
39 |
40 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
4741
48warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
42warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on foreign modules
4943 --> $DIR/incorrect-locations.rs:27:1
5044 |
5145LL | #[diagnostic::do_not_recommend]
5246 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53LL |
54LL | extern "C" {}
55 | ------------- not a trait implementation
47 |
48 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
5649
57warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
50warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on functions
5851 --> $DIR/incorrect-locations.rs:31:1
5952 |
6053LL | #[diagnostic::do_not_recommend]
6154 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62LL |
63LL | fn fun() {}
64 | ----------- not a trait implementation
55 |
56 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
6557
66warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
58warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on structs
6759 --> $DIR/incorrect-locations.rs:35:1
6860 |
6961LL | #[diagnostic::do_not_recommend]
7062 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71LL |
72LL | struct Struct {}
73 | ---------------- not a trait implementation
63 |
64 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
7465
75warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
66warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on traits
7667 --> $DIR/incorrect-locations.rs:39:1
7768 |
7869LL | #[diagnostic::do_not_recommend]
7970 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80LL |
81LL | trait Trait {}
82 | -------------- not a trait implementation
71 |
72 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
8373
8474warning: 9 warnings emitted
8575
tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.next.stderr+26-36
......@@ -1,85 +1,75 @@
1warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
1warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on constants
22 --> $DIR/incorrect-locations.rs:7:1
33 |
44LL | #[diagnostic::do_not_recommend]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6LL |
7LL | const CONST: () = ();
8 | --------------------- not a trait implementation
96 |
7 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
108 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
119
12warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
10warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on statics
1311 --> $DIR/incorrect-locations.rs:11:1
1412 |
1513LL | #[diagnostic::do_not_recommend]
1614 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17LL |
18LL | static STATIC: () = ();
19 | ----------------------- not a trait implementation
15 |
16 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
2017
21warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
18warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on type aliases
2219 --> $DIR/incorrect-locations.rs:15:1
2320 |
2421LL | #[diagnostic::do_not_recommend]
2522 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26LL |
27LL | type Type = ();
28 | --------------- not a trait implementation
23 |
24 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
2925
30warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
26warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on enums
3127 --> $DIR/incorrect-locations.rs:19:1
3228 |
3329LL | #[diagnostic::do_not_recommend]
3430 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35LL |
36LL | enum Enum {}
37 | ------------ not a trait implementation
31 |
32 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
3833
39warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
34warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on inherent impl blocks
4035 --> $DIR/incorrect-locations.rs:23:1
4136 |
4237LL | #[diagnostic::do_not_recommend]
4338 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44LL |
45LL | impl Enum {}
46 | ------------ not a trait implementation
39 |
40 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
4741
48warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
42warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on foreign modules
4943 --> $DIR/incorrect-locations.rs:27:1
5044 |
5145LL | #[diagnostic::do_not_recommend]
5246 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53LL |
54LL | extern "C" {}
55 | ------------- not a trait implementation
47 |
48 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
5649
57warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
50warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on functions
5851 --> $DIR/incorrect-locations.rs:31:1
5952 |
6053LL | #[diagnostic::do_not_recommend]
6154 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62LL |
63LL | fn fun() {}
64 | ----------- not a trait implementation
55 |
56 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
6557
66warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
58warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on structs
6759 --> $DIR/incorrect-locations.rs:35:1
6860 |
6961LL | #[diagnostic::do_not_recommend]
7062 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71LL |
72LL | struct Struct {}
73 | ---------------- not a trait implementation
63 |
64 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
7465
75warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
66warning: `#[diagnostic::do_not_recommend]` attribute cannot be used on traits
7667 --> $DIR/incorrect-locations.rs:39:1
7768 |
7869LL | #[diagnostic::do_not_recommend]
7970 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80LL |
81LL | trait Trait {}
82 | -------------- not a trait implementation
71 |
72 = help: `#[diagnostic::do_not_recommend]` can only be applied to trait impl blocks
8373
8474warning: 9 warnings emitted
8575
tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.rs+9-9
......@@ -5,39 +5,39 @@
55//@ reference: attributes.diagnostic.do_not_recommend.allowed-positions
66
77#[diagnostic::do_not_recommend]
8//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
8//~^WARN cannot be used on
99const CONST: () = ();
1010
1111#[diagnostic::do_not_recommend]
12//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
12//~^WARN cannot be used on
1313static STATIC: () = ();
1414
1515#[diagnostic::do_not_recommend]
16//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
16//~^WARN cannot be used on
1717type Type = ();
1818
1919#[diagnostic::do_not_recommend]
20//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
20//~^WARN cannot be used on
2121enum Enum {}
2222
2323#[diagnostic::do_not_recommend]
24//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
24//~^WARN cannot be used on
2525impl Enum {}
2626
2727#[diagnostic::do_not_recommend]
28//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
28//~^WARN cannot be used on
2929extern "C" {}
3030
3131#[diagnostic::do_not_recommend]
32//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
32//~^WARN cannot be used on
3333fn fun() {}
3434
3535#[diagnostic::do_not_recommend]
36//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
36//~^WARN cannot be used on
3737struct Struct {}
3838
3939#[diagnostic::do_not_recommend]
40//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
40//~^WARN cannot be used on
4141trait Trait {}
4242
4343#[diagnostic::do_not_recommend]
tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs+3-3
......@@ -2,7 +2,7 @@
22#![deny(misplaced_diagnostic_attributes)]
33
44#[diagnostic::on_const(message = "tadaa", note = "boing")]
5//~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
5//~^ ERROR: cannot be used on
66pub struct Foo;
77
88#[diagnostic::on_const(message = "tadaa", note = "boing")]
......@@ -14,7 +14,7 @@ const impl PartialEq for Foo {
1414}
1515
1616#[diagnostic::on_const(message = "tadaa", note = "boing")]
17//~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
17//~^ ERROR: cannot be used on
1818impl Foo {
1919 fn eq(&self, _other: &Foo) -> bool {
2020 true
......@@ -23,7 +23,7 @@ impl Foo {
2323
2424impl PartialOrd for Foo {
2525 #[diagnostic::on_const(message = "tadaa", note = "boing")]
26 //~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
26 //~^ ERROR: cannot be used on
2727 fn partial_cmp(&self, other: &Foo) -> Option<std::cmp::Ordering> {
2828 None
2929 }
tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr+13-22
......@@ -13,38 +13,29 @@ note: the lint level is defined here
1313LL | #![deny(misplaced_diagnostic_attributes)]
1414 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
16error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
16error: `#[diagnostic::on_const]` attribute cannot be used on structs
1717 --> $DIR/misplaced_attr.rs:4:1
1818 |
1919LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
2020 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21LL |
22LL | pub struct Foo;
23 | --------------- not a trait implementation
21 |
22 = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks
2423
25error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
24error: `#[diagnostic::on_const]` attribute cannot be used on inherent impl blocks
2625 --> $DIR/misplaced_attr.rs:16:1
2726 |
28LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
29 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30LL |
31LL | / impl Foo {
32LL | | fn eq(&self, _other: &Foo) -> bool {
33LL | | true
34LL | | }
35LL | | }
36 | |_- not a trait implementation
27LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
28 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29 |
30 = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks
3731
38error: `#[diagnostic::on_const]` can only be applied to non-const trait implementations
32error: `#[diagnostic::on_const]` attribute cannot be used on trait methods in impl blocks
3933 --> $DIR/misplaced_attr.rs:25:5
4034 |
41LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
42 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43LL |
44LL | / fn partial_cmp(&self, other: &Foo) -> Option<std::cmp::Ordering> {
45LL | | None
46LL | | }
47 | |_____- not a trait implementation
35LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 = help: `#[diagnostic::on_const]` can only be applied to trait impl blocks
4839
4940error: aborting due to 4 previous errors
5041
tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.rs+1-1
......@@ -7,7 +7,7 @@
77struct Foo;
88
99#[diagnostic::on_move(
10//~^WARN `#[diagnostic::on_move]` can only be applied to enums, structs or unions
10//~^WARN `#[diagnostic::on_move]` attribute cannot be used on traits
1111 message = "Foo",
1212 label = "Bar",
1313)]
tests/ui/diagnostic_namespace/on_move/report_warning_on_non_adt.stderr+2-1
......@@ -1,4 +1,4 @@
1warning: `#[diagnostic::on_move]` can only be applied to enums, structs or unions
1warning: `#[diagnostic::on_move]` attribute cannot be used on traits
22 --> $DIR/report_warning_on_non_adt.rs:9:1
33 |
44LL | / #[diagnostic::on_move(
......@@ -8,6 +8,7 @@ LL | | label = "Bar",
88LL | | )]
99 | |__^
1010 |
11 = help: `#[diagnostic::on_move]` can only be applied to data types
1112 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
1213
1314error[E0382]: Foo
tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.rs+6-6
......@@ -1,30 +1,30 @@
11#![feature(diagnostic_on_type_error)]
22
33#[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
4//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
4//~^ WARN cannot be used on
55fn function() {}
66
77#[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
8//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
8//~^ WARN cannot be used on
99static STATIC: i32 = 0;
1010
1111#[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
12//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
12//~^ WARN cannot be used on
1313mod module {}
1414
1515#[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
16//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
16//~^ WARN cannot be used on
1717trait Trait {}
1818
1919#[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
20//~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
20//~^ WARN cannot be used on
2121type TypeAlias = i32;
2222
2323struct SomeStruct;
2424
2525impl SomeStruct {
2626 #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
27 //~^ WARN `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
27 //~^ WARN cannot be used on
2828 fn method() {}
2929}
3030
tests/ui/diagnostic_namespace/on_type_error/report_warning_on_non_adt.stderr+17-6
......@@ -1,40 +1,51 @@
1warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
1warning: `#[diagnostic::on_type_error]` attribute cannot be used on functions
22 --> $DIR/report_warning_on_non_adt.rs:3:1
33 |
44LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 |
7 = help: `#[diagnostic::on_type_error]` can only be applied to data types
78 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
89
9warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
10warning: `#[diagnostic::on_type_error]` attribute cannot be used on statics
1011 --> $DIR/report_warning_on_non_adt.rs:7:1
1112 |
1213LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
1314 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 |
16 = help: `#[diagnostic::on_type_error]` can only be applied to data types
1417
15warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
18warning: `#[diagnostic::on_type_error]` attribute cannot be used on modules
1619 --> $DIR/report_warning_on_non_adt.rs:11:1
1720 |
1821LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
1922 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23 |
24 = help: `#[diagnostic::on_type_error]` can only be applied to data types
2025
21warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
26warning: `#[diagnostic::on_type_error]` attribute cannot be used on traits
2227 --> $DIR/report_warning_on_non_adt.rs:15:1
2328 |
2429LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
2530 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31 |
32 = help: `#[diagnostic::on_type_error]` can only be applied to data types
2633
27warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
34warning: `#[diagnostic::on_type_error]` attribute cannot be used on type aliases
2835 --> $DIR/report_warning_on_non_adt.rs:19:1
2936 |
3037LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
3138 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39 |
40 = help: `#[diagnostic::on_type_error]` can only be applied to data types
3241
33warning: `#[diagnostic::on_type_error]` can only be applied to enums, structs or unions
42warning: `#[diagnostic::on_type_error]` attribute cannot be used on inherent methods
3443 --> $DIR/report_warning_on_non_adt.rs:26:5
3544 |
3645LL | #[diagnostic::on_type_error(note = "custom on_type_error note: not an ADT")]
3746 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47 |
48 = help: `#[diagnostic::on_type_error]` can only be applied to data types
3849
3950error[E0308]: mismatched types
4051 --> $DIR/report_warning_on_non_adt.rs:38:25
tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs+1-1
......@@ -20,7 +20,7 @@ trait Foo<T> {}
2020trait Bar {}
2121
2222#[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
23//~^WARN #[diagnostic::on_unimplemented]` can only be applied to trait definitions
23//~^WARN cannot be used on
2424impl Bar for i32 {}
2525
2626// cannot use special rustc_on_unimplement symbols
tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr+2-1
......@@ -152,12 +152,13 @@ LL | #[diagnostic::on_unimplemented = "Message"]
152152 |
153153 = help: only `message`, `note` and `label` are allowed as options
154154
155warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
155warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on trait impl blocks
156156 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1
157157 |
158158LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
159159 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
160160 |
161 = help: `#[diagnostic::on_unimplemented]` can only be applied to traits
161162 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
162163
163164warning: format specifiers are not permitted in diagnostic attributes
tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs+1-1
......@@ -5,7 +5,7 @@
55trait Foo {}
66
77#[diagnostic::on_unimplemented(message = "Baz")]
8//~^WARN `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
8//~^WARN cannot be used on
99struct Bar {}
1010
1111#[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr+2-1
......@@ -16,12 +16,13 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
1616 = help: only `message`, `note` and `label` are allowed as options
1717 = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
1818
19warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
19warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on structs
2020 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:7:1
2121 |
2222LL | #[diagnostic::on_unimplemented(message = "Baz")]
2323 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424 |
25 = help: `#[diagnostic::on_unimplemented]` can only be applied to traits
2526 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
2627
2728warning: malformed `diagnostic::on_unimplemented` attribute
tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.rs+1-1
......@@ -6,7 +6,7 @@
66trait Test {}
77
88#[diagnostic::on_unimplemented(message = "blah", label = "blah", note = "blah")]
9//~^ WARN `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
9//~^ WARN cannot be used on
1010trait Alias = Test;
1111
1212// Use trait alias as bound on type parameter.
tests/ui/diagnostic_namespace/on_unimplemented/on_impl_trait.stderr+2-1
......@@ -1,9 +1,10 @@
1warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
1warning: `#[diagnostic::on_unimplemented]` attribute cannot be used on trait aliases
22 --> $DIR/on_impl_trait.rs:8:1
33 |
44LL | #[diagnostic::on_unimplemented(message = "blah", label = "blah", note = "blah")]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 |
7 = help: `#[diagnostic::on_unimplemented]` can only be applied to traits
78 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
89
910error[E0277]: the trait bound `{integer}: Alias` is not satisfied
tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.rs+11-11
......@@ -3,47 +3,47 @@
33#![feature(diagnostic_on_unknown)]
44
55#[diagnostic::on_unknown(message = "foo")]
6//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
6//~^WARN cannot be used on
77extern crate std as other_std;
88
99#[diagnostic::on_unknown(message = "foo")]
10//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
10//~^WARN cannot be used on
1111const CONST: () = ();
1212
1313#[diagnostic::on_unknown(message = "foo")]
14//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
14//~^WARN cannot be used on
1515static STATIC: () = ();
1616
1717#[diagnostic::on_unknown(message = "foo")]
18//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
18//~^WARN cannot be used on
1919type Type = ();
2020
2121#[diagnostic::on_unknown(message = "foo")]
22//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
22//~^WARN cannot be used on
2323enum Enum {}
2424
2525#[diagnostic::on_unknown(message = "foo")]
26//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
26//~^WARN cannot be used on
2727impl Enum {}
2828
2929#[diagnostic::on_unknown(message = "foo")]
30//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
30//~^WARN cannot be used on
3131extern "C" {}
3232
3333#[diagnostic::on_unknown(message = "foo")]
34//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
34//~^WARN cannot be used on
3535fn fun() {}
3636
3737#[diagnostic::on_unknown(message = "foo")]
38//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
38//~^WARN cannot be used on
3939struct Struct {}
4040
4141#[diagnostic::on_unknown(message = "foo")]
42//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
42//~^WARN cannot be used on
4343trait Trait {}
4444
4545#[diagnostic::on_unknown(message = "foo")]
46//~^WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
46//~^WARN cannot be used on
4747impl Trait for i32 {}
4848
4949#[diagnostic::on_unknown(message = "foo")]
tests/ui/diagnostic_namespace/on_unknown/incorrect_locations.stderr+32-44
......@@ -1,103 +1,91 @@
1warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
1warning: `#[diagnostic::on_unknown]` attribute cannot be used on extern crates
22 --> $DIR/incorrect_locations.rs:5:1
33 |
44LL | #[diagnostic::on_unknown(message = "foo")]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6LL |
7LL | extern crate std as other_std;
8 | ------------------------------ not an import or module
96 |
7 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
108 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
119
12warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
10warning: `#[diagnostic::on_unknown]` attribute cannot be used on constants
1311 --> $DIR/incorrect_locations.rs:9:1
1412 |
1513LL | #[diagnostic::on_unknown(message = "foo")]
1614 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17LL |
18LL | const CONST: () = ();
19 | --------------------- not an import or module
15 |
16 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
2017
21warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
18warning: `#[diagnostic::on_unknown]` attribute cannot be used on statics
2219 --> $DIR/incorrect_locations.rs:13:1
2320 |
2421LL | #[diagnostic::on_unknown(message = "foo")]
2522 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26LL |
27LL | static STATIC: () = ();
28 | ----------------------- not an import or module
23 |
24 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
2925
30warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
26warning: `#[diagnostic::on_unknown]` attribute cannot be used on type aliases
3127 --> $DIR/incorrect_locations.rs:17:1
3228 |
3329LL | #[diagnostic::on_unknown(message = "foo")]
3430 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35LL |
36LL | type Type = ();
37 | --------------- not an import or module
31 |
32 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
3833
39warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
34warning: `#[diagnostic::on_unknown]` attribute cannot be used on enums
4035 --> $DIR/incorrect_locations.rs:21:1
4136 |
4237LL | #[diagnostic::on_unknown(message = "foo")]
4338 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44LL |
45LL | enum Enum {}
46 | ------------ not an import or module
39 |
40 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
4741
48warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
42warning: `#[diagnostic::on_unknown]` attribute cannot be used on inherent impl blocks
4943 --> $DIR/incorrect_locations.rs:25:1
5044 |
5145LL | #[diagnostic::on_unknown(message = "foo")]
5246 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53LL |
54LL | impl Enum {}
55 | ------------ not an import or module
47 |
48 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
5649
57warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
50warning: `#[diagnostic::on_unknown]` attribute cannot be used on foreign modules
5851 --> $DIR/incorrect_locations.rs:29:1
5952 |
6053LL | #[diagnostic::on_unknown(message = "foo")]
6154 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62LL |
63LL | extern "C" {}
64 | ------------- not an import or module
55 |
56 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
6557
66warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
58warning: `#[diagnostic::on_unknown]` attribute cannot be used on functions
6759 --> $DIR/incorrect_locations.rs:33:1
6860 |
6961LL | #[diagnostic::on_unknown(message = "foo")]
7062 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71LL |
72LL | fn fun() {}
73 | ----------- not an import or module
63 |
64 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
7465
75warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
66warning: `#[diagnostic::on_unknown]` attribute cannot be used on structs
7667 --> $DIR/incorrect_locations.rs:37:1
7768 |
7869LL | #[diagnostic::on_unknown(message = "foo")]
7970 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80LL |
81LL | struct Struct {}
82 | ---------------- not an import or module
71 |
72 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
8373
84warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
74warning: `#[diagnostic::on_unknown]` attribute cannot be used on traits
8575 --> $DIR/incorrect_locations.rs:41:1
8676 |
8777LL | #[diagnostic::on_unknown(message = "foo")]
8878 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
89LL |
90LL | trait Trait {}
91 | -------------- not an import or module
79 |
80 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
9281
93warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
82warning: `#[diagnostic::on_unknown]` attribute cannot be used on trait impl blocks
9483 --> $DIR/incorrect_locations.rs:45:1
9584 |
9685LL | #[diagnostic::on_unknown(message = "foo")]
9786 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98LL |
99LL | impl Trait for i32 {}
100 | --------------------- not an import or module
87 |
88 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
10189
10290warning: 11 warnings emitted
10391
tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.rs+1-1
......@@ -6,6 +6,6 @@
66
77fn main() {
88 #[diagnostic::on_unknown(message = "anonymous block")]
9 //~^ WARN `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
9 //~^ WARN cannot be used on
1010 {}
1111}
tests/ui/diagnostic_namespace/on_unknown/incorrect_unstable_positions.stderr+2-4
......@@ -1,12 +1,10 @@
1warning: `#[diagnostic::on_unknown]` can only be applied to `use` statements and module declarations
1warning: `#[diagnostic::on_unknown]` attribute cannot be used on expressions
22 --> $DIR/incorrect_unstable_positions.rs:8:5
33 |
44LL | #[diagnostic::on_unknown(message = "anonymous block")]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6LL |
7LL | {}
8 | -- not an import or module
96 |
7 = help: `#[diagnostic::on_unknown]` can be applied to crates, modules, and use statements
108 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
119
1210warning: 1 warning emitted
tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.rs+1-1
......@@ -2,7 +2,7 @@
22#![feature(diagnostic_on_unmatched_args)]
33
44#[diagnostic::on_unmatched_args(message = "not allowed here")]
5//~^ WARN `#[diagnostic::on_unmatched_args]` can only be applied to macro definitions
5//~^ WARN cannot be used on
66struct Foo;
77
88fn main() {
tests/ui/diagnostic_namespace/on_unmatched_args/report_warning_on_non_macro.stderr+2-1
......@@ -1,9 +1,10 @@
1warning: `#[diagnostic::on_unmatched_args]` can only be applied to macro definitions
1warning: `#[diagnostic::on_unmatched_args]` attribute cannot be used on structs
22 --> $DIR/report_warning_on_non_macro.rs:4:1
33 |
44LL | #[diagnostic::on_unmatched_args(message = "not allowed here")]
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 |
7 = help: `#[diagnostic::on_unmatched_args]` can only be applied to macro defs
78 = note: `#[warn(misplaced_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
89
910warning: 1 warning emitted
triagebot.toml+3-1
......@@ -1531,6 +1531,7 @@ libs = [
15311531 "@clarfonthey",
15321532 "@aapoalas",
15331533 "@Darksonn",
1534 "@JohnTitor",
15341535]
15351536infra-ci = [
15361537 "@Mark-Simulacrum",
......@@ -1560,7 +1561,8 @@ diagnostics = [
15601561 "@davidtwco",
15611562 "@oli-obk",
15621563 "@chenyukang",
1563 "@TaKO8Ki"
1564 "@TaKO8Ki",
1565 "@JohnTitor",
15641566]
15651567parser = [
15661568 "@davidtwco",