diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d41108724175..2e91a1d921dd8 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -959,9 +959,9 @@ fn link_natively( } } - let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; + let level = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { - lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { + lint_level(sess, LINKER_MESSAGES, level, None, |diag| { LinkerOutput { inner: msg }.decorate_lint(diag) }) }; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d26d6edf3149d..f36e42cc6b95f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -34,7 +34,7 @@ use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -45,7 +45,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; -use rustc_session::lint::Level; use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; @@ -341,7 +340,7 @@ impl CodegenResults { /// Instead, encode exactly the information we need. #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevels { - linker_messages: (Level, LintLevelSource), + linker_messages: LevelAndSource, } impl CodegenLintLevels { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 496f6c86f7196..61a7ec13511c2 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -546,7 +546,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL, hir_id, ) - .0 + .level .is_error(); let span = ecx.cur_span(); ecx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f1dc4bb795e51..a64ffe5da8ee1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -715,7 +715,7 @@ fn print_crate_info( // lint is unstable and feature gate isn't active, don't print continue; } - let level = lint_levels.lint_level(lint).0; + let level = lint_levels.lint_level(lint).level; println_info!("{}={}", lint.name_lower(), level.as_str()); } } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f0636b600b70b..f3aeb8d224b9d 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -91,13 +91,13 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => { annotate_snippets::Level::Error } - Level::ForceWarning(_) | Level::Warning => annotate_snippets::Level::Warning, + Level::ForceWarning | Level::Warning => annotate_snippets::Level::Warning, Level::Note | Level::OnceNote => annotate_snippets::Level::Note, Level::Help | Level::OnceHelp => annotate_snippets::Level::Help, // FIXME(#59346): Not sure how to map this level Level::FailureNote => annotate_snippets::Level::Error, Level::Allow => panic!("Should not call with Allow"), - Level::Expect(_) => panic!("Should not call with Expect"), + Level::Expect => panic!("Should not call with Expect"), } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9f4d2ea5c1ad6..794502d7aaee3 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -9,7 +9,7 @@ use std::thread::panicking; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{FluentValue, fluent_value_from_str_list_sep_by_and}; -use rustc_lint_defs::Applicability; +use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -296,6 +296,7 @@ pub struct DiagInner { pub messages: Vec<(DiagMessage, Style)>, pub code: Option, + pub lint_id: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Suggestions, @@ -324,6 +325,7 @@ impl DiagInner { pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self { DiagInner { level, + lint_id: None, messages, code: None, span: MultiSpan::new(), @@ -346,7 +348,7 @@ impl DiagInner { match self.level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::ForceWarning | Level::Warning | Level::Note | Level::OnceNote @@ -354,7 +356,7 @@ impl DiagInner { | Level::OnceHelp | Level::FailureNote | Level::Allow - | Level::Expect(_) => false, + | Level::Expect => false, } } @@ -365,7 +367,7 @@ impl DiagInner { pub(crate) fn is_force_warn(&self) -> bool { match self.level { - Level::ForceWarning(_) => { + Level::ForceWarning => { assert!(self.is_lint.is_some()); true } @@ -1259,6 +1261,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + with_fn! { with_lint_id, + /// Add an argument. + #[rustc_lint_diagnostics] + pub fn lint_id( + &mut self, + id: LintExpectationId, + ) -> &mut Self { + self.lint_id = Some(id); + self + } } + with_fn! { with_primary_message, /// Add a primary message. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 7d7f364fec236..a6583407b7e7e 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -144,7 +144,7 @@ impl Emitter for JsonEmitter { // // So to avoid ICEs and confused users we "upgrade" the lint level for // those `FutureBreakageItem` to warn. - if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { + if matches!(diag.level, crate::Level::Allow | crate::Level::Expect) { diag.level = crate::Level::Warning; } FutureBreakageItem { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 80e43ede4453a..f5f7618285e1f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -905,8 +905,8 @@ impl<'a> DiagCtxtHandle<'a> { DelayedBug => { return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } - ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow - | Expect(_) => None, + ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow + | Expect => None, }; // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic @@ -1045,7 +1045,7 @@ impl<'a> DiagCtxtHandle<'a> { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. inner.emit_diagnostic( - DiagInner::new(ForceWarning(None), DiagMessage::Str(warnings)), + DiagInner::new(ForceWarning, DiagMessage::Str(warnings)), None, ); } @@ -1450,7 +1450,7 @@ impl<'a> DiagCtxtHandle<'a> { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a, ()> { - Diag::new(self, Expect(id), msg) + Diag::new(self, Expect, msg).with_lint_id(id) } } @@ -1510,7 +1510,7 @@ impl DiagCtxtInner { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and // stashed below, so they'll trigger the must_produce_diag check. - assert_matches!(diagnostic.level, Error | Warning | Allow | Expect(_)); + assert_matches!(diagnostic.level, Error | Warning | Allow | Expect); self.future_breakage_diagnostics.push(diagnostic.clone()); } @@ -1558,7 +1558,7 @@ impl DiagCtxtInner { }; } } - ForceWarning(None) => {} // `ForceWarning(Some(...))` is below, with `Expect` + ForceWarning if diagnostic.lint_id.is_none() => {} // `ForceWarning(Some(...))` is below, with `Expect` Warning => { if !self.flags.can_emit_warnings { // We are not emitting warnings. @@ -1580,9 +1580,9 @@ impl DiagCtxtInner { } return None; } - Expect(expect_id) | ForceWarning(Some(expect_id)) => { - self.fulfilled_expectations.insert(expect_id); - if let Expect(_) = diagnostic.level { + Expect | ForceWarning => { + self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap()); + if let Expect = diagnostic.level { // Nothing emitted here for expected lints. TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); self.suppressed_expected_diag = true; @@ -1631,7 +1631,7 @@ impl DiagCtxtInner { if is_error { self.deduplicated_err_count += 1; - } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { + } else if matches!(diagnostic.level, ForceWarning | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; @@ -1899,9 +1899,9 @@ pub enum Level { /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// - /// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this + /// Requires a [`LintExpectationId`] for expected lint diagnostics. In all other cases this /// should be `None`. - ForceWarning(Option), + ForceWarning, /// A warning about the code being compiled. Does not prevent compilation from finishing. /// Will be skipped if `can_emit_warnings` is false. @@ -1926,8 +1926,8 @@ pub enum Level { /// Only used for lints. Allow, - /// Only used for lints. - Expect(LintExpectationId), + /// Only used for lints. Requires a [`LintExpectationId`] for silencing the lints. + Expect, } impl fmt::Display for Level { @@ -1943,7 +1943,7 @@ impl Level { Bug | Fatal | Error | DelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } - ForceWarning(_) | Warning => { + ForceWarning | Warning => { spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); } Note | OnceNote => { @@ -1953,7 +1953,7 @@ impl Level { spec.set_fg(Some(Color::Cyan)).set_intense(true); } FailureNote => {} - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } spec } @@ -1962,11 +1962,11 @@ impl Level { match self { Bug | DelayedBug => "error: internal compiler error", Fatal | Error => "error", - ForceWarning(_) | Warning => "warning", + ForceWarning | Warning => "warning", Note | OnceNote => "note", Help | OnceHelp => "help", FailureNote => "failure-note", - Allow | Expect(_) => unreachable!(), + Allow | Expect => unreachable!(), } } @@ -1977,8 +1977,7 @@ impl Level { // Can this level be used in a subdiagnostic message? fn can_be_subdiag(&self) -> bool { match self { - Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow - | Expect(_) => false, + Bug | DelayedBug | Fatal | Error | ForceWarning | FailureNote | Allow | Expect => false, Warning | Note | Help | OnceNote | OnceHelp => true, } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 3fa06620ea8d1..b48a081d3714d 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -83,6 +83,12 @@ pub struct HirId { pub local_id: ItemLocalId, } +// To ensure correctness of incremental compilation, +// `HirId` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for HirId {} +impl !PartialOrd for HirId {} + impl Debug for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10) @@ -116,10 +122,6 @@ impl HirId { pub fn make_owner(owner: LocalDefId) -> Self { Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO } } - - pub fn index(self) -> (usize, usize) { - (rustc_index::Idx::index(self.owner.def_id), rustc_index::Idx::index(self.local_id)) - } } impl fmt::Display for HirId { @@ -128,18 +130,6 @@ impl fmt::Display for HirId { } } -impl Ord for HirId { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - (self.index()).cmp(&(other.index())) - } -} - -impl PartialOrd for HirId { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId); rustc_data_structures::define_id_collections!( ItemLocalMap, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 4a839d4057181..6bc0f797cca53 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -11,6 +11,7 @@ #![feature(debug_closure_helpers)] #![feature(exhaustive_patterns)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index b4ac143f51353..8ab71e5220bb7 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Intermediate format to store the hir_id pointing to the use that resulted in the /// corresponding place being captured and a String which contains the captured value's /// name (i.e: a.b.c) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] enum UpvarMigrationInfo { /// We previously captured all of `x`, but now we capture some sub-path. CapturingPrecise { source_expr: Option, var_name: String }, @@ -1396,14 +1396,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { FxIndexSet::default() }; - // Combine all the captures responsible for needing migrations into one HashSet + // Combine all the captures responsible for needing migrations into one IndexSet let mut capture_diagnostic = drop_reorder_diagnostic.clone(); for key in auto_trait_diagnostic.keys() { capture_diagnostic.insert(key.clone()); } let mut capture_diagnostic = capture_diagnostic.into_iter().collect::>(); - capture_diagnostic.sort(); + capture_diagnostic.sort_by_cached_key(|info| match info { + UpvarMigrationInfo::CapturingPrecise { source_expr: _, var_name } => { + (0, Some(var_name.clone())) + } + UpvarMigrationInfo::CapturingNothing { use_span: _ } => (1, None), + }); for captures_info in capture_diagnostic { // Get the auto trait reasons of why migration is needed because of that capture, if there are any let capture_trait_reasons = @@ -2323,8 +2328,9 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis( return false; } - let (level, _) = - tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id); + let level = tcx + .lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id) + .level; !matches!(level, lint::Level::Allow) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c56dbc2e1c401..dae0efcbbc465 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -29,6 +29,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; @@ -694,7 +695,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { } // Avoid listing trait impls if the trait is allowed. - let (level, _) = cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); + let LevelAndSource { level, .. } = + cx.tcx.lint_level_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()); if level == Level::Allow { return; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 017ae943e9161..885a7308bdc6d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -17,13 +17,12 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_hir::{Pat, PatKind}; use rustc_middle::bug; +use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::privacy::EffectiveVisibilities; 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::{ - FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, -}; +use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintBuffer, LintExpectationId, LintId}; use rustc_session::{LintStoreMarker, Session}; use rustc_span::edit_distance::find_best_match_for_names; use rustc_span::{Ident, Span, Symbol, sym}; @@ -573,7 +572,7 @@ pub trait LintContext { } /// This returns the lint level for the given lint at the current location. - fn get_lint_level(&self, lint: &'static Lint) -> Level; + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource; /// This function can be used to manually fulfill an expectation. This can /// be used for lints which contain several spans, and should be suppressed, @@ -642,8 +641,8 @@ impl<'tcx> LintContext for LateContext<'tcx> { } } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs).0 + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs) } } @@ -663,8 +662,8 @@ impl LintContext for EarlyContext<'_> { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate) } - fn get_lint_level(&self, lint: &'static Lint) -> Level { - self.builder.lint_level(lint).0 + fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource { + self.builder.lint_level(lint) } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 313d8f6ba8ff4..f1fe07cfcfaa4 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -84,10 +84,10 @@ impl LintLevelSets { ) -> LevelAndSource { let lint = LintId::of(lint); let (level, mut src) = self.raw_lint_id_level(lint, idx, aux); - let level = reveal_actual_level(level, &mut src, sess, lint, |id| { + let (level, lint_id) = reveal_actual_level(level, &mut src, sess, lint, |id| { self.raw_lint_id_level(id, idx, aux) }); - (level, src) + LevelAndSource { level, lint_id, src } } fn raw_lint_id_level( @@ -95,17 +95,17 @@ impl LintLevelSets { id: LintId, mut idx: LintStackIndex, aux: Option<&FxIndexMap>, - ) -> (Option, LintLevelSource) { + ) -> (Option<(Level, Option)>, LintLevelSource) { if let Some(specs) = aux - && let Some(&(level, src)) = specs.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } loop { let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); + if let Some(&LevelAndSource { level, lint_id, src }) = specs.get(&id) { + return (Some((level, lint_id)), src); } if idx == COMMAND_LINE { return (None, LintLevelSource::Default); @@ -131,8 +131,8 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { }) .filter_map(|lint| { let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID); - if matches!(lint_level, (Level::Allow, ..)) - || (matches!(lint_level, (.., LintLevelSource::Default))) + if matches!(lint_level.level, Level::Allow) + || (matches!(lint_level.src, LintLevelSource::Default)) && lint.default_level(tcx.sess.edition()) == Level::Allow { Some(LintId::of(lint)) @@ -379,13 +379,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) { if matches!( Level::from_attr(attribute), - Some( - Level::Warn - | Level::Deny - | Level::Forbid - | Level::Expect(..) - | Level::ForceWarn(..), - ) + Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _)) ) { let store = unerased_lint_store(self.tcx.sess); // Lint attributes are always a metalist inside a @@ -541,9 +535,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { for &(ref lint_name, level) in &self.sess.opts.lint_opts { // Checks the validity of lint names derived from the command line. let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name); - if lint_name_only == crate::WARNINGS.name_lower() - && matches!(level, Level::ForceWarn(_)) - { + if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn) { self.sess .dcx() .emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() }); @@ -586,7 +578,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ => {} }; - let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); let Ok(ids) = self.store.find_lints(lint_name) else { @@ -595,15 +586,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; for id in ids { // ForceWarn and Forbid cannot be overridden - if let Some((Level::ForceWarn(_) | Level::Forbid, _)) = + if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) = self.current_specs().get(&id) { continue; } if self.check_gated_lint(id, DUMMY_SP, true) { - let src = LintLevelSource::CommandLine(lint_flag_val, orig_level); - self.insert(id, (level, src)); + let src = LintLevelSource::CommandLine(lint_flag_val, level); + self.insert(id, LevelAndSource { level, lint_id: None, src }); } } } @@ -612,8 +603,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); + fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: LevelAndSource) { + let LevelAndSource { level: old_level, src: old_src, .. } = + self.provider.get_lint_level(id.lint, self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a @@ -685,7 +677,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // The lint `unfulfilled_lint_expectations` can't be expected, as it would suppress itself. // Handling expectations of this lint would add additional complexity with little to no // benefit. The expect level for this lint will therefore be ignored. - if let Level::Expect(_) = level + if let Level::Expect = level && id == LintId::of(UNFULFILLED_LINT_EXPECTATIONS) { return; @@ -693,13 +685,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { match (old_level, level) { // If the new level is an expectation store it in `ForceWarn` - (Level::ForceWarn(_), Level::Expect(expectation_id)) => { - self.insert(id, (Level::ForceWarn(Some(expectation_id)), old_src)) + (Level::ForceWarn, Level::Expect) => { + self.insert(id, LevelAndSource { level: Level::ForceWarn, lint_id, src: old_src }) } // Keep `ForceWarn` level but drop the expectation - (Level::ForceWarn(_), _) => self.insert(id, (Level::ForceWarn(None), old_src)), + (Level::ForceWarn, _) => self.insert( + id, + LevelAndSource { level: Level::ForceWarn, lint_id: None, src: old_src }, + ), // Set the lint level as normal - _ => self.insert(id, (level, src)), + _ => self.insert(id, LevelAndSource { level, lint_id, src }), }; } @@ -714,7 +709,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if attr.has_name(sym::automatically_derived) { self.insert( LintId::of(SINGLE_USE_LIFETIMES), - (Level::Allow, LintLevelSource::Default), + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, ); continue; } @@ -725,15 +724,22 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { .meta_item_list() .is_some_and(|l| ast::attr::list_contains_name(&l, sym::hidden)) { - self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default)); + self.insert( + LintId::of(MISSING_DOCS), + LevelAndSource { + level: Level::Allow, + lint_id: None, + src: LintLevelSource::Default, + }, + ); continue; } - let level = match Level::from_attr(attr) { + let (level, lint_id) = match Level::from_attr(attr) { None => continue, // This is the only lint level with a `LintExpectationId` that can be created from // an attribute. - Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { + Some((Level::Expect, Some(unstable_id))) if let Some(hir_id) = source_hir_id => { let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id else { bug!("stable id Level::from_attr") @@ -745,9 +751,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { lint_index: None, }; - Level::Expect(stable_id) + (Level::Expect, Some(stable_id)) } - Some(lvl) => lvl, + Some((lvl, id)) => (lvl, id), }; let Some(mut metas) = attr.meta_item_list() else { continue }; @@ -795,13 +801,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } for (lint_index, li) in metas.iter_mut().enumerate() { - let level = match level { - Level::Expect(mut id) => { - id.set_lint_index(Some(lint_index as u16)); - Level::Expect(id) - } - level => level, - }; + let mut lint_id = lint_id; + if let Some(id) = &mut lint_id { + id.set_lint_index(Some(lint_index as u16)); + } let sp = li.span(); let meta_item = match li { @@ -933,7 +936,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let src = LintLevelSource::Node { name, span: sp, reason }; for &id in ids { if self.check_gated_lint(id, sp, false) { - self.insert_spec(id, (level, src)); + self.insert_spec(id, LevelAndSource { level, lint_id, src }); } } @@ -942,7 +945,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // overriding the lint level but instead add an expectation that can't be // fulfilled. The lint message will include an explanation, that the // `unfulfilled_lint_expectations` lint can't be expected. - if let Level::Expect(expect_id) = level { + if let (Level::Expect, Some(expect_id)) = (level, lint_id) { // The `unfulfilled_lint_expectations` lint is not part of any lint // groups. Therefore. we only need to check the slice if it contains a // single lint. @@ -964,7 +967,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } if self.lint_added_lints && !is_crate_node { - for (id, &(level, ref src)) in self.current_specs().iter() { + for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() { if !id.lint.crate_level_only { continue; } @@ -1002,10 +1005,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if self.lint_added_lints { let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); + let level = self.lint_level(builtin::UNKNOWN_LINTS); // FIXME: make this translatable #[allow(rustc::diagnostic_outside_of_impl)] - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + lint_level(self.sess, lint, level, Some(span.into()), |lint| { lint.primary_message(fluent::lint_unknown_gated_lint); lint.arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); @@ -1040,8 +1043,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: Option, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, span, decorate) + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, span, decorate) } #[track_caller] @@ -1051,16 +1054,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { span: MultiSpan, decorate: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, Some(span), |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, Some(span), |lint| { decorate.decorate_lint(lint); }); } #[track_caller] pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) { - let (level, src) = self.lint_level(lint); - lint_level(self.sess, lint, level, src, None, |lint| { + let level = self.lint_level(lint); + lint_level(self.sess, lint, level, None, |lint| { decorate.decorate_lint(lint); }); } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 66e207a451ef0..9c11fb41aa6d6 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -159,12 +159,13 @@ impl EarlyLintPass for NonAsciiIdents { use rustc_span::Span; use unicode_security::GeneralSecurityProfile; - let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).0 != Level::Allow; + let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).level != Level::Allow; let check_uncommon_codepoints = - cx.builder.lint_level(UNCOMMON_CODEPOINTS).0 != Level::Allow; - let check_confusable_idents = cx.builder.lint_level(CONFUSABLE_IDENTS).0 != Level::Allow; + cx.builder.lint_level(UNCOMMON_CODEPOINTS).level != Level::Allow; + let check_confusable_idents = + cx.builder.lint_level(CONFUSABLE_IDENTS).level != Level::Allow; let check_mixed_script_confusables = - cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).0 != Level::Allow; + cx.builder.lint_level(MIXED_SCRIPT_CONFUSABLES).level != Level::Allow; if !check_non_ascii_idents && !check_uncommon_codepoints diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 46b4b1d438386..7fdbae3a59d7e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,7 +8,8 @@ use rustc_data_structures::stable_hasher::{ }; use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; -use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; +use rustc_hir::def_id::DefPathHash; +use rustc_hir::{HashStableContext, HirId, ItemLocalId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; pub use rustc_span::edition::Edition; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym}; @@ -102,7 +103,7 @@ pub enum Applicability { /// The index values have a type of `u16` to reduce the size of the `LintExpectationId`. /// It's reasonable to assume that no user will define 2^16 attributes on one node or /// have that amount of lints listed. `u16` values should therefore suffice. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)] pub enum LintExpectationId { /// Used for lints emitted during the `EarlyLintPass`. This id is not /// hash stable and should not be cached. @@ -156,13 +157,14 @@ impl HashStable for LintExpectationId { } impl ToStableHashKey for LintExpectationId { - type KeyType = (HirId, u16, u16); + type KeyType = (DefPathHash, ItemLocalId, u16, u16); #[inline] - fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { + fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType { match self { LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { - (*hir_id, *attr_index, *lint_index) + let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx); + (def_path_hash, lint_idx, *attr_index, *lint_index) } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") @@ -199,9 +201,9 @@ pub enum Level { /// /// See RFC 2383. /// - /// The [`LintExpectationId`] is used to later link a lint emission to the actual + /// Requires a [`LintExpectationId`] to later link a lint emission to the actual /// expectation. It can be ignored in most cases. - Expect(LintExpectationId), + Expect, /// The `warn` level will produce a warning if the lint was violated, however the /// compiler will continue with its execution. Warn, @@ -209,9 +211,9 @@ pub enum Level { /// to ensure that a lint can't be suppressed. This lint level can currently only be set /// via the console and is therefore session specific. /// - /// The [`LintExpectationId`] is intended to fulfill expectations marked via the + /// Requires a [`LintExpectationId`] to fulfill expectations marked via the /// `#[expect]` attribute, that will still be suppressed due to the level. - ForceWarn(Option), + ForceWarn, /// The `deny` level will produce an error and stop further execution after the lint /// pass is complete. Deny, @@ -225,9 +227,9 @@ impl Level { pub fn as_str(self) -> &'static str { match self { Level::Allow => "allow", - Level::Expect(_) => "expect", + Level::Expect => "expect", Level::Warn => "warn", - Level::ForceWarn(_) => "force-warn", + Level::ForceWarn => "force-warn", Level::Deny => "deny", Level::Forbid => "forbid", } @@ -246,24 +248,30 @@ impl Level { } /// Converts an `Attribute` to a level. - pub fn from_attr(attr: &impl AttributeExt) -> Option { + pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option)> { Self::from_symbol(attr.name_or_empty(), || Some(attr.id())) } /// Converts a `Symbol` to a level. - pub fn from_symbol(s: Symbol, id: impl FnOnce() -> Option) -> Option { + pub fn from_symbol( + s: Symbol, + id: impl FnOnce() -> Option, + ) -> Option<(Self, Option)> { match s { - sym::allow => Some(Level::Allow), + sym::allow => Some((Level::Allow, None)), sym::expect => { if let Some(attr_id) = id() { - Some(Level::Expect(LintExpectationId::Unstable { attr_id, lint_index: None })) + Some(( + Level::Expect, + Some(LintExpectationId::Unstable { attr_id, lint_index: None }), + )) } else { None } } - sym::warn => Some(Level::Warn), - sym::deny => Some(Level::Deny), - sym::forbid => Some(Level::Forbid), + sym::warn => Some((Level::Warn, None)), + sym::deny => Some((Level::Deny, None)), + sym::forbid => Some((Level::Forbid, None)), _ => None, } } @@ -274,8 +282,8 @@ impl Level { Level::Deny => "-D", Level::Forbid => "-F", Level::Allow => "-A", - Level::ForceWarn(_) => "--force-warn", - Level::Expect(_) => { + Level::ForceWarn => "--force-warn", + Level::Expect => { unreachable!("the expect level does not have a commandline flag") } } @@ -283,17 +291,10 @@ impl Level { pub fn is_error(self) -> bool { match self { - Level::Allow | Level::Expect(_) | Level::Warn | Level::ForceWarn(_) => false, + Level::Allow | Level::Expect | Level::Warn | Level::ForceWarn => false, Level::Deny | Level::Forbid => true, } } - - pub fn get_expectation_id(&self) -> Option { - match self { - Level::Expect(id) | Level::ForceWarn(Some(id)) => Some(*id), - _ => None, - } - } } /// Specification of a single lint. diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 16f87ab79bee5..1c3222bbfeb61 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -340,7 +340,7 @@ impl CStore { } let level = tcx .lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID) - .0; + .level; if level != lint::Level::Allow { let unused_externs = self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::>(); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 88bf17070b9c5..d5a408fdfa6a3 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -51,8 +51,13 @@ impl LintLevelSource { } } -/// A tuple of a lint level and its source. -pub type LevelAndSource = (Level, LintLevelSource); +/// Convenience helper for moving things around together that frequently are paired +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub struct LevelAndSource { + pub level: Level, + pub lint_id: Option, + pub src: LintLevelSource, +} /// Return type for the `shallow_lint_levels_on` query. /// @@ -69,14 +74,18 @@ pub struct ShallowLintLevelMap { /// /// The return of this function is suitable for diagnostics. pub fn reveal_actual_level( - level: Option, + level: Option<(Level, Option)>, src: &mut LintLevelSource, sess: &Session, lint: LintId, - probe_for_lint_level: impl FnOnce(LintId) -> (Option, LintLevelSource), -) -> Level { + probe_for_lint_level: impl FnOnce( + LintId, + ) + -> (Option<(Level, Option)>, LintLevelSource), +) -> (Level, Option) { // If `level` is none then we actually assume the default level for this lint. - let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); + let (mut level, mut lint_id) = + level.unwrap_or_else(|| (lint.lint.default_level(sess.edition()), None)); // If we're about to issue a warning, check at the last minute for any // directives against the warnings "lint". If, for example, there's an @@ -88,16 +97,17 @@ pub fn reveal_actual_level( // future compatibility warning. if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { + if let Some((configured_warning_level, configured_lint_id)) = warnings_level { if configured_warning_level != Level::Warn { level = configured_warning_level; + lint_id = configured_lint_id; *src = warnings_src; } } } // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn - level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src { level } else { cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid)) @@ -108,7 +118,7 @@ pub fn reveal_actual_level( level = cmp::min(*driver_level, level); } - level + (level, lint_id) } impl ShallowLintLevelMap { @@ -121,11 +131,11 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, id: LintId, start: HirId, - ) -> (Option, LintLevelSource) { + ) -> (Option<(Level, Option)>, LintLevelSource) { if let Some(map) = self.specs.get(&start.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } let mut owner = start.owner; @@ -137,9 +147,9 @@ impl ShallowLintLevelMap { specs = &tcx.shallow_lint_levels_on(owner).specs; } if let Some(map) = specs.get(&parent.local_id) - && let Some(&(level, src)) = map.get(&id) + && let Some(&LevelAndSource { level, lint_id, src }) = map.get(&id) { - return (Some(level), src); + return (Some((level, lint_id)), src); } } @@ -153,18 +163,18 @@ impl ShallowLintLevelMap { tcx: TyCtxt<'_>, lint: LintId, cur: HirId, - ) -> (Level, LintLevelSource) { + ) -> LevelAndSource { let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur); - let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { + let (level, lint_id) = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { self.probe_for_lint_level(tcx, lint, cur) }); - (level, src) + LevelAndSource { level, lint_id, src } } } impl TyCtxt<'_> { /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { + pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> LevelAndSource { self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id) } } @@ -267,8 +277,7 @@ fn explain_lint_level_source( pub fn lint_level( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { @@ -278,11 +287,12 @@ pub fn lint_level( fn lint_level_impl( sess: &Session, lint: &'static Lint, - level: Level, - src: LintLevelSource, + level: LevelAndSource, span: Option, decorate: Box FnOnce(&'b mut Diag<'a, ()>)>, ) { + let LevelAndSource { level, lint_id, src } = level; + // Check for future incompatibility lints and issue a stronger warning. let future_incompatible = lint.future_incompatible; @@ -301,7 +311,7 @@ pub fn lint_level( return; } } - Level::Expect(expect_id) => { + Level::Expect => { // This case is special as we actually allow the lint itself in this context, but // we can't return early like in the case for `Level::Allow` because we still // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. @@ -309,10 +319,9 @@ pub fn lint_level( // We can also not mark the lint expectation as fulfilled here right away, as it // can still be cancelled in the decorate function. All of this means that we simply // create a `Diag` and continue as we would for warnings. - rustc_errors::Level::Expect(expect_id) + rustc_errors::Level::Expect } - Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::ForceWarning(Some(expect_id)), - Level::ForceWarn(None) => rustc_errors::Level::ForceWarning(None), + Level::ForceWarn => rustc_errors::Level::ForceWarning, Level::Warn => rustc_errors::Level::Warning, Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; @@ -320,6 +329,9 @@ pub fn lint_level( if let Some(span) = span { err.span(span); } + if let Some(lint_id) = lint_id { + err.lint_id(lint_id); + } // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate @@ -350,7 +362,7 @@ pub fn lint_level( // the compiler. It is therefore not necessary to add any information for the user. // This will therefore directly call the decorate function which will in turn emit // the diagnostic. - if let Level::Expect(_) = level { + if let Level::Expect = level { decorate(&mut err); err.emit(); return; @@ -419,5 +431,5 @@ pub fn lint_level( explain_lint_level_source(lint, level, src, &mut err); err.emit() } - lint_level_impl(sess, lint, level, src, span, Box::new(decorate)) + lint_level_impl(sess, lint, level, span, Box::new(decorate)) } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index ec128c8c47863..9912e659b05f5 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -255,7 +255,7 @@ fn late_report_deprecation( // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if tcx.lint_level_at_node(lint, hir_id).0 == Level::Allow { + if tcx.lint_level_at_node(lint, hir_id).level == Level::Allow { return; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 618a65a018644..f064bdb257665 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3022,8 +3022,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into, decorator: impl for<'a> LintDiagnostic<'a, ()>, ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), |lint| { decorator.decorate_lint(lint); }) } @@ -3040,8 +3040,8 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, hir_id); - lint_level(self.sess, lint, level, src, Some(span.into()), decorate); + let level = self.lint_level_at_node(lint, hir_id); + lint_level(self.sess, lint, level, Some(span.into()), decorate); } /// Find the crate root and the appropriate span where `use` and outer attributes can be @@ -3108,8 +3108,8 @@ impl<'tcx> TyCtxt<'tcx> { id: HirId, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), ) { - let (level, src) = self.lint_level_at_node(lint, id); - lint_level(self.sess, lint, level, src, None, decorate); + let level = self.lint_level_at_node(lint, id); + lint_level(self.sess, lint, level, None, decorate); } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> { diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 90e27c85f749a..fbe530811567f 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -159,7 +159,7 @@ fn find_capture_matching_projections<'a, 'tcx>( ) -> Option<(usize, &'a Capture<'tcx>)> { let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections); - upvars.get_by_key_enumerated(var_hir_id.0).find(|(_, capture)| { + upvars.get_by_key_enumerated(var_hir_id.0.local_id).find(|(_, capture)| { let possible_ancestor_proj_kinds: Vec<_> = capture.captured_place.place.projections.iter().map(|proj| proj.kind).collect(); is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections) diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index bcc2a4674ead4..8ca9ab58e4571 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -13,7 +13,7 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Node}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -221,7 +221,7 @@ struct Builder<'a, 'tcx> { coverage_info: Option, } -type CaptureMap<'tcx> = SortedIndexMultiMap>; +type CaptureMap<'tcx> = SortedIndexMultiMap>; #[derive(Debug)] struct Capture<'tcx> { @@ -853,6 +853,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let capture_tys = upvar_args.upvar_tys(); let tcx = self.tcx; + let mut upvar_owner = None; self.upvars = tcx .closure_captures(self.def_id) .iter() @@ -866,6 +867,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, _ => bug!("Expected an upvar"), }; + let upvar_base = upvar_owner.get_or_insert(var_id.owner); + assert_eq!(*upvar_base, var_id.owner); + let var_id = var_id.local_id; let mutability = captured_place.mutability; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2a9bfb25b8421..6fb9974fc8e27 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -195,7 +195,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node. fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool { - self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow + self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).level == Level::Allow } /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body. @@ -292,8 +292,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }); } BlockSafety::ExplicitUnsafe(hir_id) => { - let used = - matches!(self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id), (Level::Allow, _)); + let used = matches!( + self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id).level, + Level::Allow + ); self.in_safety_context( SafetyContext::UnsafeBlock { span: block.span, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index ea8c7303c0afa..9f5e2c06b229d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1025,7 +1025,7 @@ fn find_fallback_pattern_typo<'tcx>( pat: &Pat<'tcx>, lint: &mut UnreachablePattern<'_>, ) { - if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) { + if let Level::Allow = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id).level { // This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd // ICE. At the same time, we don't really need to do all of this if we won't emit anything. return; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b62d94d65f1f4..0060e726a8e05 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -19,8 +19,8 @@ use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; +use rustc_session::lint::{self, LintExpectationId}; use rustc_span::{Symbol, sym}; use crate::errors::{ @@ -696,8 +696,8 @@ fn has_allow_dead_code_or_lang_attr( fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def_id); - let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0; - matches!(lint_level, lint::Allow | lint::Expect(_)) + let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level; + matches!(lint_level, lint::Allow | lint::Expect) } fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { @@ -915,7 +915,7 @@ fn live_symbols_and_ignored_derived_traits( struct DeadItem { def_id: LocalDefId, name: Symbol, - level: lint::Level, + level: (lint::Level, Option), } struct DeadVisitor<'tcx> { @@ -959,9 +959,10 @@ impl<'tcx> DeadVisitor<'tcx> { ShouldWarnAboutField::Yes } - fn def_lint_level(&self, id: LocalDefId) -> lint::Level { + fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option) { let hir_id = self.tcx.local_def_id_to_hir_id(id); - self.tcx.lint_level_at_node(DEAD_CODE, hir_id).0 + let level = self.tcx.lint_level_at_node(DEAD_CODE, hir_id); + (level.level, level.lint_id) } // # Panics @@ -1129,7 +1130,8 @@ impl<'tcx> DeadVisitor<'tcx> { if dead_codes.is_empty() { return; } - dead_codes.sort_by_key(|v| v.level); + // FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>` + dead_codes.sort_by_key(|v| v.level.0); for group in dead_codes.chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 6dec96f9f502f..d7baad69c7861 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -980,7 +980,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // Calculating message for lint involves calling `self.def_path_str`, // which will by default invoke the expensive `visible_parent_map` query. // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_at_node(DEPRECATED, id).0 + if self.tcx.lint_level_at_node(DEPRECATED, id).level == lint::Level::Allow { return; diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 585cda1d24b7f..3da744dc8c029 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,3 +1,4 @@ +use rustc_middle::lint::LevelAndSource; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; use tracing::instrument; @@ -64,7 +65,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { if !matches!( - rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, + rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).level, rustc_session::lint::Level::Allow ) { let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?; @@ -88,13 +89,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( // arm. This no longer makes sense so we warn users, to avoid silently breaking their // usage of the lint. for arm in arms { - let (lint_level, lint_level_source) = + let LevelAndSource { level, src, .. } = rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); - if !matches!(lint_level, rustc_session::lint::Level::Allow) { + if !matches!(level, rustc_session::lint::Level::Allow) { let decorator = NonExhaustiveOmittedPatternLintOnArm { - lint_span: lint_level_source.span(), + lint_span: src.span(), suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), - lint_level: lint_level.as_str(), + lint_level: level.as_str(), lint_name: "non_exhaustive_omitted_patterns", }; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 1b01efda2a9ea..1f18950feac35 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1700,7 +1700,7 @@ pub fn get_cmd_lint_options( let mut lint_opts_with_position = vec![]; let mut describe_lints = false; - for level in [lint::Allow, lint::Warn, lint::ForceWarn(None), lint::Deny, lint::Forbid] { + for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] { for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f8f670f575bf4..761282bde7c30 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -5,7 +5,7 @@ use std::ops; use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use rustc_span::FileName; use serde::Serialize; @@ -216,7 +216,8 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); - let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); + let LevelAndSource { level, src, .. } = + self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); // In case we have: // @@ -251,7 +252,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { // unless the user had an explicit `allow`. // let should_have_docs = !should_be_ignored - && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); + && (level != lint::Level::Allow || matches!(src, LintLevelSource::Default)); if let Some(span) = i.span(self.ctx.tcx) { let filename = span.filename(self.ctx.sess()); diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0fefd13f76333..70dbb944d4c0a 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -6,7 +6,7 @@ //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. use rustc_hir as hir; -use rustc_middle::lint::LintLevelSource; +use rustc_middle::lint::{LevelAndSource, LintLevelSource}; use rustc_session::lint; use tracing::debug; @@ -107,11 +107,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - { return false; } - let (level, source) = cx.tcx.lint_level_at_node( + let LevelAndSource { level, src, .. } = cx.tcx.lint_level_at_node( crate::lint::MISSING_DOC_CODE_EXAMPLES, cx.tcx.local_def_id_to_hir_id(def_id), ); - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) + level != lint::Level::Allow || matches!(src, LintLevelSource::Default) } pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 48b5d4da88860..7bb5dbee126ed 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -199,7 +199,7 @@ fn check_simplify_not(cx: &LateContext<'_>, msrv: Msrv, expr: &Expr<'_>) { && !expr.span.from_expansion() && !inner.span.from_expansion() && let Some(suggestion) = simplify_not(cx, msrv, inner) - && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow + && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).level != Level::Allow { use clippy_utils::sugg::{Sugg, has_enclosing_paren}; let maybe_par = if let Some(sug) = Sugg::hir_opt(cx, inner) { @@ -605,7 +605,7 @@ impl<'tcx> NonminimalBoolVisitor<'_, 'tcx> { } } let nonminimal_bool_lint = |mut suggestions: Vec<_>| { - if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow { + if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).level != Level::Allow { suggestions.sort(); span_lint_hir_and_then( self.cx, diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index 53c24a3faf1d8..d1a8590c59b4d 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -69,7 +69,7 @@ impl EarlyLintPass for DisallowedScriptIdents { // Implementation is heavily inspired by the implementation of [`non_ascii_idents`] lint: // https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint/src/non_ascii_idents.rs - let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).0 != Level::Allow; + let check_disallowed_script_idents = cx.builder.lint_level(DISALLOWED_SCRIPT_IDENTS).level != Level::Allow; if !check_disallowed_script_idents { return; } diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 243c99a19ce1b..ce551a64d9984 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Crate, Inline, Item, ItemKind, ModKind}; use rustc_errors::MultiSpan; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; +use rustc_middle::lint::LevelAndSource; use rustc_session::impl_lint_pass; use rustc_span::{FileName, Span}; use std::collections::BTreeMap; @@ -45,11 +46,10 @@ declare_clippy_lint! { "file loaded as module multiple times" } -#[derive(PartialOrd, Ord, PartialEq, Eq)] struct Modules { local_path: PathBuf, spans: Vec, - lint_levels: Vec, + lint_levels: Vec, } #[derive(Default)] @@ -95,11 +95,11 @@ impl EarlyLintPass for DuplicateMod { .iter() .zip(lint_levels) .filter_map(|(span, lvl)| { - if let Some(id) = lvl.get_expectation_id() { + if let Some(id) = lvl.lint_id { cx.fulfill_expectation(id); } - (!matches!(lvl, Level::Allow | Level::Expect(_))).then_some(*span) + (!matches!(lvl.level, Level::Allow | Level::Expect)).then_some(*span) }) .collect(); diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index cc3d972f017b8..3fe3cd67e1671 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -408,9 +408,9 @@ mod zombie_processes; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; -use utils::attr_collector::{AttrCollector, AttrStorage}; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; +use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index b712b351d063c..98ad1f6a160d8 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -153,9 +153,15 @@ impl LateLintPass<'_> for MacroUseImports { [] | [_] => return, [root, item] => { if !check_dup.contains(&(*item).to_string()) { - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push((*item).to_string()); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push((*item).to_string()); check_dup.push((*item).to_string()); } }, @@ -171,15 +177,27 @@ impl LateLintPass<'_> for MacroUseImports { } }) .collect::>(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(filtered.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(filtered.join("::")); check_dup.extend(filtered); } else { let rest = rest.to_vec(); - used.entry(((*root).to_string(), span, hir_id)) - .or_insert_with(Vec::new) - .push(rest.join("::")); + used.entry(( + (*root).to_string(), + span, + hir_id.local_id, + cx.tcx.def_path_hash(hir_id.owner.def_id.into()), + )) + .or_insert_with(|| (vec![], hir_id)) + .0 + .push(rest.join("::")); check_dup.extend(rest.iter().map(ToString::to_string)); } }, @@ -190,7 +208,7 @@ impl LateLintPass<'_> for MacroUseImports { // If mac_refs is not empty we have encountered an import we could not handle // such as `std::prelude::v1::foo` or some other macro that expands to an import. if self.mac_refs.is_empty() { - for ((root, span, hir_id), path) in used { + for ((root, span, ..), (path, hir_id)) in used { let import = if let [single] = &path[..] { format!("{root}::{single}") } else { diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index 676d608eb318c..7287193326f7a 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -73,8 +73,8 @@ impl_lint_pass!(ModStyle => [MOD_MODULE_FILES, SELF_NAMED_MODULE_FILES]); impl EarlyLintPass for ModStyle { fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { - if cx.builder.lint_level(MOD_MODULE_FILES).0 == Level::Allow - && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).0 == Level::Allow + if cx.builder.lint_level(MOD_MODULE_FILES).level == Level::Allow + && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).level == Level::Allow { return; } diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index c6e6e782f9d45..6a79cae32a596 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -138,7 +138,7 @@ impl RawStrings { ); }, ); - if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) { + if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS).level, rustc_lint::Allow) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 4cb73df8b488f..d8e8ead291288 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -404,7 +404,7 @@ fn check_final_expr<'tcx>( match cx.tcx.hir_attrs(expr.hir_id) { [] => {}, [attr] => { - if matches!(Level::from_attr(attr), Some(Level::Expect(_))) + if matches!(Level::from_attr(attr), Some((Level::Expect, _))) && let metas = attr.meta_item_list() && let Some(lst) = metas && let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice() diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8dc28fa3077e0..6d2c2a2d692e1 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -114,6 +114,7 @@ use rustc_hir::{ use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -1976,14 +1977,14 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I let mut suppress_lint = false; for id in ids { - let (level, _) = cx.tcx.lint_level_at_node(lint, id); - if let Some(expectation) = level.get_expectation_id() { + let LevelAndSource { level, lint_id, .. } = cx.tcx.lint_level_at_node(lint, id); + if let Some(expectation) = lint_id { cx.fulfill_expectation(expectation); } match level { - Level::Allow | Level::Expect(_) => suppress_lint = true, - Level::Warn | Level::ForceWarn(_) | Level::Deny | Level::Forbid => {}, + Level::Allow | Level::Expect => suppress_lint = true, + Level::Warn | Level::ForceWarn | Level::Deny | Level::Forbid => {}, } } @@ -1998,7 +1999,7 @@ pub fn fulfill_or_allowed(cx: &LateContext<'_>, lint: &'static Lint, ids: impl I /// make sure to use `span_lint_hir` functions to emit the lint. This ensures that /// expectations at the checked nodes will be fulfilled. pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool { - cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow + cx.tcx.lint_level_at_node(lint, id).level == Level::Allow } pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {