From ab780fa48aa49463301620ec825da3376c0171a3 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 14 Dec 2024 17:33:57 +0100 Subject: [PATCH 1/8] Access `TyCtxt` from early diagnostic decoration --- compiler/rustc_interface/src/passes.rs | 2 + compiler/rustc_lint/src/context.rs | 36 +--------- compiler/rustc_lint/src/early.rs | 65 +++++++++++++++---- .../src/{context => early}/diagnostics.rs | 8 ++- .../diagnostics/check_cfg.rs | 0 5 files changed, 62 insertions(+), 49 deletions(-) rename compiler/rustc_lint/src/{context => early}/diagnostics.rs (99%) rename compiler/rustc_lint/src/{context => early}/diagnostics/check_cfg.rs (100%) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 430bc7db0775b..f8351a81bec64 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -76,6 +76,7 @@ fn pre_expansion_lint<'a>( || { rustc_lint::check_ast_node( sess, + None, features, true, lint_store, @@ -310,6 +311,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let lint_store = unerased_lint_store(tcx.sess); rustc_lint::check_ast_node( sess, + Some(tcx), tcx.features(), false, lint_store, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 44c7888a530ca..d8d901698d611 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode}; use rustc_session::lint::{ - BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, + FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, }; use rustc_session::{LintStoreMarker, Session}; use rustc_span::Span; @@ -33,8 +33,6 @@ use self::TargetLint::*; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; -mod diagnostics; - type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync; type LateLintPassFactory = dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync; @@ -511,38 +509,6 @@ pub struct EarlyContext<'a> { pub buffered: LintBuffer, } -impl EarlyContext<'_> { - /// Emit a lint at the appropriate level, with an associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: MultiSpan, - diagnostic: BuiltinLintDiag, - ) { - self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic); - } - - /// Emit a lint at the appropriate level, with an optional associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn opt_span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: Option, - diagnostic: BuiltinLintDiag, - ) { - self.opt_span_lint(lint, span, |diag| { - diagnostics::decorate_lint(self.sess(), diagnostic, diag); - }); - } -} - pub trait LintContext { fn sess(&self) -> &Session; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index a68a2a7f98380..6d1081700d7ab 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -8,36 +8,73 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::MultiSpan; use rustc_feature::Features; -use rustc_middle::ty::RegisteredTools; +use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; -use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; +use rustc_session::lint::{BufferedEarlyLint, BuiltinLintDiag, LintBuffer, LintPass}; use rustc_span::Span; use rustc_span::symbol::Ident; use tracing::debug; -use crate::context::{EarlyContext, LintStore}; +use crate::Lint; +use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; +mod diagnostics; + macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } /// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. -pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { +pub struct EarlyContextAndPass<'a, 'b, T: EarlyLintPass> { context: EarlyContext<'a>, + tcx: Option>, pass: T, } -impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { +impl EarlyContextAndPass<'_, '_, T> { + /// Emit a lint at the appropriate level, with an associated span and an existing + /// diagnostic. + /// + /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature + #[rustc_lint_diagnostics] + pub fn span_lint_with_diagnostics( + &self, + lint: &'static Lint, + span: MultiSpan, + diagnostic: BuiltinLintDiag, + ) { + self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic); + } + + /// Emit a lint at the appropriate level, with an optional associated span and an existing + /// diagnostic. + /// + /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature + #[rustc_lint_diagnostics] + pub fn opt_span_lint_with_diagnostics( + &self, + lint: &'static Lint, + span: Option, + diagnostic: BuiltinLintDiag, + ) { + self.context.opt_span_lint(lint, span, |diag| { + diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag); + }); + } +} + +impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { // This always-inlined function is for the hot call site. #[inline(always)] #[allow(rustc::diagnostic_outside_of_impl)] fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic); + self.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic); } } @@ -67,7 +104,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { } } -impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { +impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, 'b, T> { fn visit_coroutine_kind(&mut self, coroutine_kind: &'a ast::CoroutineKind) -> Self::Result { self.check_id(coroutine_kind.closure_id()); } @@ -313,7 +350,7 @@ pub trait EarlyCheckNode<'a>: Copy { fn attrs<'b>(self) -> &'b [ast::Attribute] where 'a: 'b; - fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) + fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) where 'a: 'b; } @@ -328,7 +365,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { { self.1 } - fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>) + fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) where 'a: 'b, { @@ -348,7 +385,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P(self, cx: &mut EarlyContextAndPass<'b, T>) + fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) where 'a: 'b, { @@ -359,6 +396,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P( sess: &Session, + tcx: Option>, features: &Features, pre_expansion: bool, lint_store: &LintStore, @@ -382,22 +420,23 @@ pub fn check_ast_node<'a>( let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; if passes.is_empty() { - check_ast_node_inner(sess, check_node, context, builtin_lints); + check_ast_node_inner(sess, tcx, check_node, context, builtin_lints); } else { let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect(); passes.push(Box::new(builtin_lints)); let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] }; - check_ast_node_inner(sess, check_node, context, pass); + check_ast_node_inner(sess, tcx, check_node, context, pass); } } fn check_ast_node_inner<'a, T: EarlyLintPass>( sess: &Session, + tcx: Option>, check_node: impl EarlyCheckNode<'a>, context: EarlyContext<'_>, pass: T, ) { - let mut cx = EarlyContextAndPass { context, pass }; + let mut cx = EarlyContextAndPass { context, tcx, pass }; cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs similarity index 99% rename from compiler/rustc_lint/src/context/diagnostics.rs rename to compiler/rustc_lint/src/early/diagnostics.rs index a3731e31c2bd6..7f136672a47de 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -8,6 +8,7 @@ use rustc_errors::{ Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion, }; use rustc_middle::middle::stability; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_span::BytePos; @@ -18,7 +19,12 @@ use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; -pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) { +pub(super) fn decorate_lint( + sess: &Session, + _tcx: Option>, + diagnostic: BuiltinLintDiag, + diag: &mut Diag<'_, ()>, +) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { let spans: Vec<_> = content diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs similarity index 100% rename from compiler/rustc_lint/src/context/diagnostics/check_cfg.rs rename to compiler/rustc_lint/src/early/diagnostics/check_cfg.rs From c448e35af57303fc5be1dabc4384c468439ee776 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 15 Dec 2024 00:27:32 +0100 Subject: [PATCH 2/8] Simplify `opt_span_lint` call in early diagnostic --- compiler/rustc_lint/src/early.rs | 40 ++++---------------------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 6d1081700d7ab..44f724225d990 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -8,16 +8,14 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::MultiSpan; use rustc_feature::Features; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; -use rustc_session::lint::{BufferedEarlyLint, BuiltinLintDiag, LintBuffer, LintPass}; +use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_span::Span; use rustc_span::symbol::Ident; use tracing::debug; -use crate::Lint; use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; @@ -35,38 +33,6 @@ pub struct EarlyContextAndPass<'a, 'b, T: EarlyLintPass> { pass: T, } -impl EarlyContextAndPass<'_, '_, T> { - /// Emit a lint at the appropriate level, with an associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: MultiSpan, - diagnostic: BuiltinLintDiag, - ) { - self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic); - } - - /// Emit a lint at the appropriate level, with an optional associated span and an existing - /// diagnostic. - /// - /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature - #[rustc_lint_diagnostics] - pub fn opt_span_lint_with_diagnostics( - &self, - lint: &'static Lint, - span: Option, - diagnostic: BuiltinLintDiag, - ) { - self.context.opt_span_lint(lint, span, |diag| { - diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag); - }); - } -} - impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { // This always-inlined function is for the hot call site. #[inline(always)] @@ -74,7 +40,9 @@ impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic); + self.context.opt_span_lint(lint_id.lint, span, |diag| { + diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag); + }); } } From da535b9155fdab852dfd18006a5585612e50a70c Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 10 Dec 2024 03:03:28 -0500 Subject: [PATCH 3/8] Fix `--nocapture` for run-make tests This was confusing because there are three layers of output hiding. 1. libtest shoves all output into a buffer and does not print it unless the test fails or `--nocapture` is passed. 2. compiletest chooses whether to print the output from any given process. 3. run-make-support chooses what output to print. This modifies 2 and 3. - compiletest: Don't require both `--verbose` and `--nocapture` to show the output of run-make tests. - compiletest: Distinguish rustc and rmake stderr by printing the command name (e.g. "--stderr--" to "--rustc stderr--"). - run-make-support: Unconditionally print the needle/haystack being searched. Previously this was only printed on failure. Before: ``` $ x t tests/run-make/linker-warning --force-rerun -- --nocapture running 1 tests . test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 281.64ms $ x t tests/run-make/linker-warning --force-rerun -v -- --nocapture 2>&1 | wc -l 1004 $ x t tests/run-make/linker-warning --force-rerun -v -- --nocapture | tail -n40 running 1 tests ------stdout------------------------------ ------stderr------------------------------ warning: unused import: `std::path::Path` --> /home/jyn/src/rust2/tests/run-make/linker-warning/rmake.rs:1:5 | 1 | use std::path::Path; | ^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused import: `run_make_support::rfs::remove_file` --> /home/jyn/src/rust2/tests/run-make/linker-warning/rmake.rs:3:5 | 3 | use run_make_support::rfs::remove_file; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: 2 warnings emitted ------------------------------------------ test [run-make] tests/run-make/linker-warning ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 285.89ms ``` After: ``` Testing stage1 compiletest suite=run-make mode=run-make (x86_64-unknown-linux-gnu) running 1 tests ------rmake stdout------------------------------ ------rmake stderr------------------------------ assert_contains_regex: === HAYSTACK === error: linking with `./fake-linker` failed: exit status: 1 | = note: LC_ALL="C" PATH="/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin:...:/bin" VSLANG="1033" "./fake-linker" "-m64" "/tmp/rustcYqdAZT/symbols.o" "main.main.d17f5fbe6225cf88-cgu.0.rcgu.o" "main.2uoctswmurc6ir5rvoay0p9ke.rcgu.o" "-Wl,--as-needed" "-Wl,-Bstatic" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-B/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/test/run-make/linker-warning/rmake_out" "-L" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" = note: error: baz error: aborting due to 1 previous error === NEEDLE === fake-linker.*run_make_error assert_not_contains_regex: === HAYSTACK === === NEEDLE === fake-linker.*run_make_error ------------------------------------------ . test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 314.81ms ``` --- src/tools/compiletest/src/runtest.rs | 38 +++++++----- src/tools/compiletest/src/runtest/run_make.rs | 13 ++--- .../run-make-support/src/assertion_helpers.rs | 58 ++++++++----------- 3 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7b11bf3b1219c..4a4494a1e23d1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -410,7 +410,12 @@ impl<'test> TestCx<'test> { truncated: Truncated::No, cmdline: format!("{cmd:?}"), }; - self.dump_output(&proc_res.stdout, &proc_res.stderr); + self.dump_output( + self.config.verbose, + &cmd.get_program().to_string_lossy(), + &proc_res.stdout, + &proc_res.stderr, + ); proc_res } @@ -1401,7 +1406,12 @@ impl<'test> TestCx<'test> { cmdline, }; - self.dump_output(&result.stdout, &result.stderr); + self.dump_output( + self.config.verbose, + &command.get_program().to_string_lossy(), + &result.stdout, + &result.stderr, + ); result } @@ -1816,12 +1826,22 @@ impl<'test> TestCx<'test> { } } - fn dump_output(&self, out: &str, err: &str) { + fn dump_output(&self, print_output: bool, proc_name: &str, out: &str, err: &str) { let revision = if let Some(r) = self.revision { format!("{}.", r) } else { String::new() }; self.dump_output_file(out, &format!("{}out", revision)); self.dump_output_file(err, &format!("{}err", revision)); - self.maybe_dump_to_stdout(out, err); + + if !print_output { + return; + } + + let proc_name = Path::new(proc_name).file_name().unwrap().to_string_lossy(); + println!("------{proc_name} stdout------------------------------"); + println!("{}", out); + println!("------{proc_name} stderr------------------------------"); + println!("{}", err); + println!("------------------------------------------"); } fn dump_output_file(&self, out: &str, extension: &str) { @@ -1874,16 +1894,6 @@ impl<'test> TestCx<'test> { output_base_name(self.config, self.testpaths, self.safe_revision()) } - fn maybe_dump_to_stdout(&self, out: &str, err: &str) { - if self.config.verbose { - println!("------stdout------------------------------"); - println!("{}", out); - println!("------stderr------------------------------"); - println!("{}", err); - println!("------------------------------------------"); - } - } - fn error(&self, err: &str) { match self.revision { Some(rev) => println!("\nerror in revision `{}`: {}", rev, err), diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 04bc2d7787da7..85ade5b727a3b 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -517,14 +517,13 @@ impl TestCx<'_> { let proc = disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`")); let (Output { stdout, stderr, status }, truncated) = self.read2_abbreviated(proc); + let stdout = String::from_utf8_lossy(&stdout).into_owned(); + let stderr = String::from_utf8_lossy(&stderr).into_owned(); + // This conditions on `status.success()` so we don't print output twice on error. + // NOTE: this code is called from a libtest thread, so it's hidden by default unless --nocapture is passed. + self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr); if !status.success() { - let res = ProcRes { - status, - stdout: String::from_utf8_lossy(&stdout).into_owned(), - stderr: String::from_utf8_lossy(&stderr).into_owned(), - truncated, - cmdline: format!("{:?}", cmd), - }; + let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) }; self.fatal_proc_rec("rmake recipe failed to complete", &res); } } diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs index b4da65aff4ab1..e84a3cf633f97 100644 --- a/src/tools/run-make-support/src/assertion_helpers.rs +++ b/src/tools/run-make-support/src/assertion_helpers.rs @@ -5,16 +5,31 @@ use std::path::Path; use crate::{fs, regex}; +fn print<'a, 'e, A: AsRef, E: AsRef>( + assertion_kind: &str, + haystack: &'a A, + needle: &'e E, +) -> (&'a str, &'e str) { + let haystack = haystack.as_ref(); + let needle = needle.as_ref(); + eprintln!("{assertion_kind}:"); + eprintln!("=== HAYSTACK ==="); + eprintln!("{}", haystack); + eprintln!("=== NEEDLE ==="); + eprintln!("{}", needle); + (haystack, needle) +} + /// Assert that `actual` is equal to `expected`. #[track_caller] pub fn assert_equals, E: AsRef>(actual: A, expected: E) { let actual = actual.as_ref(); let expected = expected.as_ref(); + eprintln!("=== ACTUAL TEXT ==="); + eprintln!("{}", actual); + eprintln!("=== EXPECTED ==="); + eprintln!("{}", expected); if actual != expected { - eprintln!("=== ACTUAL TEXT ==="); - eprintln!("{}", actual); - eprintln!("=== EXPECTED ==="); - eprintln!("{}", expected); panic!("expected text was not found in actual text"); } } @@ -22,13 +37,8 @@ pub fn assert_equals, E: AsRef>(actual: A, expected: E) { /// Assert that `haystack` contains `needle`. #[track_caller] pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); + let (haystack, needle) = print("assert_contains", &haystack, &needle); if !haystack.contains(needle) { - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); panic!("needle was not found in haystack"); } } @@ -36,13 +46,8 @@ pub fn assert_contains, N: AsRef>(haystack: H, needle: N) { /// Assert that `haystack` does not contain `needle`. #[track_caller] pub fn assert_not_contains, N: AsRef>(haystack: H, needle: N) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); + let (haystack, needle) = print("assert_not_contains", &haystack, &needle); if haystack.contains(needle) { - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); panic!("needle was unexpectedly found in haystack"); } } @@ -50,14 +55,9 @@ pub fn assert_not_contains, N: AsRef>(haystack: H, needle: N) /// Assert that `haystack` contains the regex pattern `needle`. #[track_caller] pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: N) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); + let (haystack, needle) = print("assert_contains_regex", &haystack, &needle); let re = regex::Regex::new(needle).unwrap(); if !re.is_match(haystack) { - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); panic!("needle was not found in haystack"); } } @@ -65,14 +65,9 @@ pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: /// Assert that `haystack` does not contain the regex pattern `needle`. #[track_caller] pub fn assert_not_contains_regex, N: AsRef>(haystack: H, needle: N) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); + let (haystack, needle) = print("assert_not_contains_regex", &haystack, &needle); let re = regex::Regex::new(needle).unwrap(); if re.is_match(haystack) { - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); panic!("needle was unexpectedly found in haystack"); } } @@ -80,13 +75,8 @@ pub fn assert_not_contains_regex, N: AsRef>(haystack: H, need /// Assert that `haystack` contains `needle` a `count` number of times. #[track_caller] pub fn assert_count_is, N: AsRef>(count: usize, haystack: H, needle: N) { - let haystack = haystack.as_ref(); - let needle = needle.as_ref(); + let (haystack, needle) = print("assert_count_is", &haystack, &needle); if count != haystack.matches(needle).count() { - eprintln!("=== HAYSTACK ==="); - eprintln!("{}", haystack); - eprintln!("=== NEEDLE ==="); - eprintln!("{}", needle); panic!("needle did not appear {count} times in haystack"); } } From 056eb758e7e68df9c1cdcc3a91a07372df4de49c Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 12 Dec 2024 08:07:59 -0500 Subject: [PATCH 4/8] show which test the `rmake` process belongs to --- src/tools/compiletest/src/runtest.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4a4494a1e23d1..8af4325e7b106 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{self, File, create_dir_all}; use std::hash::{DefaultHasher, Hash, Hasher}; use std::io::prelude::*; @@ -1836,7 +1836,20 @@ impl<'test> TestCx<'test> { return; } - let proc_name = Path::new(proc_name).file_name().unwrap().to_string_lossy(); + let path = Path::new(proc_name); + let proc_name = if path.file_stem().is_some_and(|p| p == "rmake") { + OsString::from_iter( + path.parent() + .unwrap() + .file_name() + .into_iter() + .chain(Some(OsStr::new("/"))) + .chain(path.file_name()), + ) + } else { + path.file_name().unwrap().into() + }; + let proc_name = proc_name.to_string_lossy(); println!("------{proc_name} stdout------------------------------"); println!("{}", out); println!("------{proc_name} stderr------------------------------"); From 56b8e66c66206cd4ba0f4cf036cdf3dddb219816 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 15 Dec 2024 15:26:50 +0900 Subject: [PATCH 5/8] Add m68k_target_feature --- compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 18 +++++++++++++++++- tests/ui/check-cfg/target_feature.stderr | 8 ++++++++ tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 45c63b03fe98b..76b9bee4b00dc 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -332,6 +332,7 @@ declare_features! ( (unstable, hexagon_target_feature, "1.27.0", Some(44839)), (unstable, lahfsahf_target_feature, "1.78.0", Some(44839)), (unstable, loongarch_target_feature, "1.73.0", Some(44839)), + (unstable, m68k_target_feature, "CURRENT_RUSTC_VERSION", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e3708896ba946..0b29bd7a0d7b8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1190,6 +1190,7 @@ symbols! { loongarch_target_feature, loop_break_value, lt, + m68k_target_feature, macro_at_most_once_rep, macro_attributes_in_derive_output, macro_escape, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 29d3f826a1544..1256e5b4374de 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -668,6 +668,20 @@ const SPARC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +const M68K_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("isa-68000", unstable(sym::m68k_target_feature), &[]), + ("isa-68010", unstable(sym::m68k_target_feature), &["isa-68000"]), + ("isa-68020", unstable(sym::m68k_target_feature), &["isa-68010"]), + ("isa-68030", unstable(sym::m68k_target_feature), &["isa-68020"]), + ("isa-68040", unstable(sym::m68k_target_feature), &["isa-68030", "isa-68882"]), + ("isa-68060", unstable(sym::m68k_target_feature), &["isa-68040"]), + // FPU + ("isa-68881", unstable(sym::m68k_target_feature), &[]), + ("isa-68882", unstable(sym::m68k_target_feature), &["isa-68881"]), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -687,6 +701,7 @@ pub fn all_rust_features() -> impl Iterator LOONGARCH_FEATURES, "s390x" => IBMZ_FEATURES, "sparc" | "sparc64" => SPARC_FEATURES, + "m68k" => M68K_FEATURES, _ => &[], } } @@ -751,7 +767,7 @@ impl Target { "sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI, "hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI, - "bpf" => &[], // no vector ABI + "bpf" | "m68k" => &[], // no vector ABI "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI, // FIXME: for some tier3 targets, we are overly cautious and always give warnings // when passing args in vector registers. diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index e2ceb66948255..70fec8a350aa1 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -118,6 +118,14 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `hvx-length128b` `hwdiv` `i8mm` +`isa-68000` +`isa-68010` +`isa-68020` +`isa-68030` +`isa-68040` +`isa-68060` +`isa-68881` +`isa-68882` `jsconv` `lahfsahf` `lasx` diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 2626685fa0a77..14fdad02f5665 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -25,6 +25,7 @@ // gate-test-s390x_target_feature // gate-test-sparc_target_feature // gate-test-x87_target_feature +// gate-test-m68k_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index ba5ae79f942df..fa876893848f7 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:29:18 + --> $DIR/gate.rs:30:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 4795399ab6f11b648822f4ebdc06499a4d038888 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 15 Dec 2024 09:55:44 +0100 Subject: [PATCH 6/8] bootstrap: make ./x test error-index work --- src/bootstrap/src/core/build_steps/test.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 30fdea7e19e51..8d9d2b6b6a138 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2442,7 +2442,9 @@ impl Step for ErrorIndex { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/error_index_generator") + // Also add `error-index` here since that is what appears in the error message + // when this fails. + run.path("src/tools/error_index_generator").alias("error-index") } fn make_run(run: RunConfig<'_>) { From e3e5bd95cd306160cfa799b3717583fec01c7793 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 15 Dec 2024 17:15:55 +0100 Subject: [PATCH 7/8] Cleanup lifetimes around `EarlyContextAndPass` and `EarlyCheckNode` --- compiler/rustc_lint/src/early.rs | 102 +++++++++++++------------------ 1 file changed, 44 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 44f724225d990..a15aab32aee64 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -27,13 +27,13 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ /// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. -pub struct EarlyContextAndPass<'a, 'b, T: EarlyLintPass> { - context: EarlyContext<'a>, - tcx: Option>, +pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { + context: EarlyContext<'ecx>, + tcx: Option>, pass: T, } -impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { +impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { // This always-inlined function is for the hot call site. #[inline(always)] #[allow(rustc::diagnostic_outside_of_impl)] @@ -54,7 +54,7 @@ impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. - fn with_lint_attrs(&mut self, id: ast::NodeId, attrs: &'a [ast::Attribute], f: F) + fn with_lint_attrs(&mut self, id: ast::NodeId, attrs: &'_ [ast::Attribute], f: F) where F: FnOnce(&mut Self), { @@ -72,19 +72,21 @@ impl<'a, 'b, T: EarlyLintPass> EarlyContextAndPass<'a, 'b, T> { } } -impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, 'b, T> { - fn visit_coroutine_kind(&mut self, coroutine_kind: &'a ast::CoroutineKind) -> Self::Result { +impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> + for EarlyContextAndPass<'ecx, 'tcx, T> +{ + fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast ast::CoroutineKind) -> Self::Result { self.check_id(coroutine_kind.closure_id()); } - fn visit_param(&mut self, param: &'a ast::Param) { + fn visit_param(&mut self, param: &'ast ast::Param) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { lint_callback!(cx, check_param, param); ast_visit::walk_param(cx, param); }); } - fn visit_item(&mut self, it: &'a ast::Item) { + fn visit_item(&mut self, it: &'ast ast::Item) { self.with_lint_attrs(it.id, &it.attrs, |cx| { lint_callback!(cx, check_item, it); ast_visit::walk_item(cx, it); @@ -92,31 +94,31 @@ impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a }) } - fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) { + fn visit_foreign_item(&mut self, it: &'ast ast::ForeignItem) { self.with_lint_attrs(it.id, &it.attrs, |cx| { ast_visit::walk_item(cx, it); }) } - fn visit_pat(&mut self, p: &'a ast::Pat) { + fn visit_pat(&mut self, p: &'ast ast::Pat) { lint_callback!(self, check_pat, p); self.check_id(p.id); ast_visit::walk_pat(self, p); lint_callback!(self, check_pat_post, p); } - fn visit_pat_field(&mut self, field: &'a ast::PatField) { + fn visit_pat_field(&mut self, field: &'ast ast::PatField) { self.with_lint_attrs(field.id, &field.attrs, |cx| { ast_visit::walk_pat_field(cx, field); }); } - fn visit_anon_const(&mut self, c: &'a ast::AnonConst) { + fn visit_anon_const(&mut self, c: &'ast ast::AnonConst) { self.check_id(c.id); ast_visit::walk_anon_const(self, c); } - fn visit_expr(&mut self, e: &'a ast::Expr) { + fn visit_expr(&mut self, e: &'ast ast::Expr) { self.with_lint_attrs(e.id, &e.attrs, |cx| { lint_callback!(cx, check_expr, e); ast_visit::walk_expr(cx, e); @@ -124,13 +126,13 @@ impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a }) } - fn visit_expr_field(&mut self, f: &'a ast::ExprField) { + fn visit_expr_field(&mut self, f: &'ast ast::ExprField) { self.with_lint_attrs(f.id, &f.attrs, |cx| { ast_visit::walk_expr_field(cx, f); }) } - fn visit_stmt(&mut self, s: &'a ast::Stmt) { + fn visit_stmt(&mut self, s: &'ast ast::Stmt) { // Add the statement's lint attributes to our // current state when checking the statement itself. // This allows us to handle attributes like @@ -150,33 +152,33 @@ impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a ast_visit::walk_stmt(self, s); } - fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) { + fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId) { lint_callback!(self, check_fn, fk, span, id); self.check_id(id); ast_visit::walk_fn(self, fk); } - fn visit_variant_data(&mut self, s: &'a ast::VariantData) { + fn visit_variant_data(&mut self, s: &'ast ast::VariantData) { if let Some(ctor_node_id) = s.ctor_node_id() { self.check_id(ctor_node_id); } ast_visit::walk_struct_def(self, s); } - fn visit_field_def(&mut self, s: &'a ast::FieldDef) { + fn visit_field_def(&mut self, s: &'ast ast::FieldDef) { self.with_lint_attrs(s.id, &s.attrs, |cx| { ast_visit::walk_field_def(cx, s); }) } - fn visit_variant(&mut self, v: &'a ast::Variant) { + fn visit_variant(&mut self, v: &'ast ast::Variant) { self.with_lint_attrs(v.id, &v.attrs, |cx| { lint_callback!(cx, check_variant, v); ast_visit::walk_variant(cx, v); }) } - fn visit_ty(&mut self, t: &'a ast::Ty) { + fn visit_ty(&mut self, t: &'ast ast::Ty) { lint_callback!(self, check_ty, t); self.check_id(t.id); ast_visit::walk_ty(self, t); @@ -186,55 +188,55 @@ impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a lint_callback!(self, check_ident, ident); } - fn visit_local(&mut self, l: &'a ast::Local) { + fn visit_local(&mut self, l: &'ast ast::Local) { self.with_lint_attrs(l.id, &l.attrs, |cx| { lint_callback!(cx, check_local, l); ast_visit::walk_local(cx, l); }) } - fn visit_block(&mut self, b: &'a ast::Block) { + fn visit_block(&mut self, b: &'ast ast::Block) { lint_callback!(self, check_block, b); self.check_id(b.id); ast_visit::walk_block(self, b); } - fn visit_arm(&mut self, a: &'a ast::Arm) { + fn visit_arm(&mut self, a: &'ast ast::Arm) { self.with_lint_attrs(a.id, &a.attrs, |cx| { lint_callback!(cx, check_arm, a); ast_visit::walk_arm(cx, a); }) } - fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) { + fn visit_generic_arg(&mut self, arg: &'ast ast::GenericArg) { lint_callback!(self, check_generic_arg, arg); ast_visit::walk_generic_arg(self, arg); } - fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { + fn visit_generic_param(&mut self, param: &'ast ast::GenericParam) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { lint_callback!(cx, check_generic_param, param); ast_visit::walk_generic_param(cx, param); }); } - fn visit_generics(&mut self, g: &'a ast::Generics) { + fn visit_generics(&mut self, g: &'ast ast::Generics) { lint_callback!(self, check_generics, g); ast_visit::walk_generics(self, g); } - fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) { + fn visit_where_predicate(&mut self, p: &'ast ast::WherePredicate) { lint_callback!(self, enter_where_predicate, p); ast_visit::walk_where_predicate(self, p); lint_callback!(self, exit_where_predicate, p); } - fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) { + fn visit_poly_trait_ref(&mut self, t: &'ast ast::PolyTraitRef) { lint_callback!(self, check_poly_trait_ref, t); ast_visit::walk_poly_trait_ref(self, t); } - fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) { + fn visit_assoc_item(&mut self, item: &'ast ast::AssocItem, ctxt: ast_visit::AssocCtxt) { self.with_lint_attrs(item.id, &item.attrs, |cx| { match ctxt { ast_visit::AssocCtxt::Trait => { @@ -248,32 +250,32 @@ impl<'a, 'b, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a }); } - fn visit_lifetime(&mut self, lt: &'a ast::Lifetime, _: ast_visit::LifetimeCtxt) { + fn visit_lifetime(&mut self, lt: &'ast ast::Lifetime, _: ast_visit::LifetimeCtxt) { self.check_id(lt.id); ast_visit::walk_lifetime(self, lt); } - fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) { + fn visit_path(&mut self, p: &'ast ast::Path, id: ast::NodeId) { self.check_id(id); ast_visit::walk_path(self, p); } - fn visit_path_segment(&mut self, s: &'a ast::PathSegment) { + fn visit_path_segment(&mut self, s: &'ast ast::PathSegment) { self.check_id(s.id); ast_visit::walk_path_segment(self, s); } - fn visit_attribute(&mut self, attr: &'a ast::Attribute) { + fn visit_attribute(&mut self, attr: &'ast ast::Attribute) { lint_callback!(self, check_attribute, attr); ast_visit::walk_attribute(self, attr); } - fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) { + fn visit_mac_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) { lint_callback!(self, check_mac_def, mac); self.check_id(id); } - fn visit_mac_call(&mut self, mac: &'a ast::MacCall) { + fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) { lint_callback!(self, check_mac, mac); ast_visit::walk_mac(self, mac); } @@ -315,28 +317,18 @@ crate::early_lint_methods!(impl_early_lint_pass, []); /// This trait generalizes over those nodes. pub trait EarlyCheckNode<'a>: Copy { fn id(self) -> ast::NodeId; - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b; - fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) - where - 'a: 'b; + fn attrs(self) -> &'a [ast::Attribute]; + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>); } impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { fn id(self) -> ast::NodeId { ast::CRATE_NODE_ID } - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b, - { + fn attrs(self) -> &'a [ast::Attribute] { self.1 } - fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) - where - 'a: 'b, - { + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) { lint_callback!(cx, check_crate, self.0); ast_visit::walk_crate(cx, self.0); lint_callback!(cx, check_crate_post, self.0); @@ -347,16 +339,10 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P ast::NodeId { self.0 } - fn attrs<'b>(self) -> &'b [ast::Attribute] - where - 'a: 'b, - { + fn attrs(self) -> &'a [ast::Attribute] { self.1 } - fn check<'b, 'c, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, 'c, T>) - where - 'a: 'b, - { + fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) { walk_list!(cx, visit_attribute, self.1); walk_list!(cx, visit_item, self.2); } From 291c519c6966bb18e13d66a4283380ced339c49f Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 15 Dec 2024 12:52:04 +0100 Subject: [PATCH 8/8] Improve check-cfg Cargo macro diagnostic with crate name --- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/early/diagnostics.rs | 6 +++--- .../src/early/diagnostics/check_cfg.rs | 16 +++++++++++----- compiler/rustc_lint/src/lints.rs | 3 +-- .../report-in-external-macros.cargo.stderr | 6 +++--- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 01d9ac20fae89..48d6d6bbf6788 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -806,7 +806,7 @@ lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_printl lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` -lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` +lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` lint_unexpected_cfg_doc_cargo = see for more information about checking conditional configuration diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 7f136672a47de..b0fb1e4af7667 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -21,7 +21,7 @@ mod check_cfg; pub(super) fn decorate_lint( sess: &Session, - _tcx: Option>, + tcx: Option>, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>, ) { @@ -205,10 +205,10 @@ pub(super) fn decorate_lint( .decorate_lint(diag); } BuiltinLintDiag::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, name, value).decorate_lint(diag); + check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag); } BuiltinLintDiag::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, name, value).decorate_lint(diag); + check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag); } BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { let suggestion = match sugg { diff --git a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs index 63a722f606762..033c0fa4c880b 100644 --- a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs @@ -1,5 +1,6 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::ExpectedValues; use rustc_span::edit_distance::find_best_match_for_name; @@ -73,17 +74,20 @@ fn rustc_macro_help(span: Span) -> Option { } } -fn cargo_macro_help(span: Span) -> Option { +fn cargo_macro_help( + tcx: Option>, + span: Span, +) -> Option { let oexpn = span.ctxt().outer_expn_data(); if let Some(def_id) = oexpn.macro_def_id && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind && def_id.krate != LOCAL_CRATE + && let Some(tcx) = tcx { Some(lints::UnexpectedCfgCargoMacroHelp { macro_kind: macro_kind.descr(), macro_name, - // FIXME: Get access to a `TyCtxt` from an `EarlyContext` - // crate_name: cx.tcx.crate_name(def_id.krate), + crate_name: tcx.crate_name(def_id.krate), }) } else { None @@ -92,6 +96,7 @@ fn cargo_macro_help(span: Span) -> Option { pub(super) fn unexpected_cfg_name( sess: &Session, + tcx: Option>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, ) -> lints::UnexpectedCfgName { @@ -223,7 +228,7 @@ pub(super) fn unexpected_cfg_name( }; lints::unexpected_cfg_name::InvocationHelp::Cargo { help, - macro_help: cargo_macro_help(name_span), + macro_help: cargo_macro_help(tcx, name_span), } } else { let help = lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No)); @@ -238,6 +243,7 @@ pub(super) fn unexpected_cfg_name( pub(super) fn unexpected_cfg_value( sess: &Session, + tcx: Option>, (name, name_span): (Symbol, Span), value: Option<(Symbol, Span)>, ) -> lints::UnexpectedCfgValue { @@ -339,7 +345,7 @@ pub(super) fn unexpected_cfg_value( }; lints::unexpected_cfg_value::InvocationHelp::Cargo { help, - macro_help: cargo_macro_help(name_span), + macro_help: cargo_macro_help(tcx, name_span), } } else { let help = if can_suggest_adding_value { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5da9f6d205351..4977b3971bd10 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2187,8 +2187,7 @@ pub(crate) struct UnexpectedCfgRustcMacroHelp { pub(crate) struct UnexpectedCfgCargoMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, - // FIXME: Figure out a way to get the crate name - // crate_name: String, + pub crate_name: Symbol, } #[derive(LintDiagnostic)] diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr index 6fb397b5529b5..d70fedf55a30c 100644 --- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr @@ -7,7 +7,7 @@ LL | cfg_macro::my_lib_macro!(); = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg - = help: the macro `cfg_macro::my_lib_macro` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = help: the macro `cfg_macro::my_lib_macro` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -21,7 +21,7 @@ LL | cfg_macro::my_lib_macro_value!(); = note: expected values for `panic` are: `abort` and `unwind` = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg - = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro` = note: see for more information about checking conditional configuration = note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -34,7 +34,7 @@ LL | cfg_macro::my_lib_macro_feature!(); = note: no expected values for `feature` = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg - = help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of it's defining crate, try updating your dependencies with `cargo update` + = help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro` = note: see for more information about checking conditional configuration = note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info)