diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /compiler/rustc_passes/src | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 111 | ||||
-rw-r--r-- | compiler/rustc_passes/src/check_const.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_passes/src/dead.rs | 36 | ||||
-rw-r--r-- | compiler/rustc_passes/src/debugger_visualizer.rs | 127 | ||||
-rw-r--r-- | compiler/rustc_passes/src/diagnostic_items.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/entry.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/errors.rs | 164 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_id_validator.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_stats.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lang_items.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lib.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lib_features.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 242 | ||||
-rw-r--r-- | compiler/rustc_passes/src/loops.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/naked_functions.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_passes/src/reachable.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/stability.rs | 68 | ||||
-rw-r--r-- | compiler/rustc_passes/src/upvars.rs | 2 |
18 files changed, 439 insertions, 345 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 80a93da2b..c3189d1fe 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,6 @@ use crate::{errors, fluent_generated as fluent}; use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan}; -use rustc_expand::base::resolve_path; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -19,9 +18,9 @@ use rustc_hir::{ use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; +use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, @@ -29,7 +28,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -101,12 +100,11 @@ impl CheckAttrVisitor<'_> { item: Option<ItemLike<'_>>, ) { let mut doc_aliases = FxHashMap::default(); - let mut is_valid = true; let mut specified_inline = None; let mut seen = FxHashMap::default(); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - let attr_is_valid = match attr.name_or_empty() { + match attr.name_or_empty() { sym::do_not_recommend => self.check_do_not_recommend(attr.span, target), sym::inline => self.check_inline(hir_id, attr, span, target), sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target), @@ -188,7 +186,6 @@ impl CheckAttrVisitor<'_> { sym::link_ordinal => self.check_link_ordinal(&attr, span, target), _ => true, }; - is_valid &= attr_is_valid; // lint-only checks match attr.name_or_empty() { @@ -255,10 +252,6 @@ impl CheckAttrVisitor<'_> { self.check_unused_attribute(hir_id, attr) } - if !is_valid { - return; - } - self.check_repr(attrs, span, target, item, hir_id); self.check_used(attrs, target); } @@ -927,30 +920,18 @@ impl CheckAttrVisitor<'_> { hir_id: HirId, ) -> bool { if hir_id != CRATE_HIR_ID { - self.tcx.struct_span_lint_hir( + // insert a bang between `#` and `[...` + let bang_span = attr.span.lo() + BytePos(1); + let sugg = (attr.style == AttrStyle::Outer + && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID) + .then_some(errors::AttrCrateLevelOnlySugg { + attr: attr.span.with_lo(bang_span).with_hi(bang_span), + }); + self.tcx.emit_spanned_lint( INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), - fluent::passes_attr_crate_level, - |err| { - if attr.style == AttrStyle::Outer - && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID - { - if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) { - src.insert(1, '!'); - err.span_suggestion_verbose( - attr.span, - fluent::passes_suggestion, - src, - Applicability::MaybeIncorrect, - ); - } else { - err.span_help(attr.span, fluent::passes_help); - } - } - err.note(fluent::passes_note); - err - }, + errors::AttrCrateLevelOnly { sugg }, ); return false; } @@ -1728,7 +1709,9 @@ impl CheckAttrVisitor<'_> { } } sym::align => { - if let (Target::Fn, false) = (target, self.tcx.features().fn_align) { + if let (Target::Fn | Target::Method(MethodKind::Inherent), false) = + (target, self.tcx.features().fn_align) + { feature_err( &self.tcx.sess.parse_sess, sym::fn_align, @@ -1739,10 +1722,14 @@ impl CheckAttrVisitor<'_> { } match target { - Target::Struct | Target::Union | Target::Enum | Target::Fn => continue, + Target::Struct + | Target::Union + | Target::Enum + | Target::Fn + | Target::Method(_) => continue, _ => { self.tcx.sess.emit_err( - errors::AttrApplication::StructEnumFunctionUnion { + errors::AttrApplication::StructEnumFunctionMethodUnion { hint_span: hint.span(), span, }, @@ -1829,7 +1816,7 @@ impl CheckAttrVisitor<'_> { || (is_simd && is_c) || (int_reprs == 1 && is_c - && item.map_or(false, |item| { + && item.is_some_and(|item| { if let ItemLike::Item(item) = item { return is_c_like_enum(item); } @@ -1928,6 +1915,10 @@ impl CheckAttrVisitor<'_> { /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool { + // Here we only check that the #[debugger_visualizer] attribute is attached + // to nothing other than a module. All other checks are done in the + // `debugger_visualizer` query where they need to be done for decoding + // anyway. match target { Target::Mod => {} _ => { @@ -1936,53 +1927,7 @@ impl CheckAttrVisitor<'_> { } } - let Some(hints) = attr.meta_item_list() else { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - }; - - let hint = match hints.len() { - 1 => &hints[0], - _ => { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - } - }; - - let Some(meta_item) = hint.meta_item() else { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - }; - - let visualizer_path = match (meta_item.name_or_empty(), meta_item.value_str()) { - (sym::natvis_file, Some(value)) => value, - (sym::gdb_script_file, Some(value)) => value, - (_, _) => { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span }); - return false; - } - }; - - let file = - match resolve_path(&self.tcx.sess.parse_sess, visualizer_path.as_str(), attr.span) { - Ok(file) => file, - Err(mut err) => { - err.emit(); - return false; - } - }; - - match std::fs::File::open(&file) { - Ok(_) => true, - Err(error) => { - self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable { - span: meta_item.span, - file: &file, - error, - }); - false - } - } + true } /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. @@ -2150,7 +2095,7 @@ impl CheckAttrVisitor<'_> { | sym::feature | sym::repr | sym::target_feature - ) && attr.meta_item_list().map_or(false, |list| list.is_empty()) + ) && attr.meta_item_list().is_some_and(|list| list.is_empty()) { errors::UnusedNote::EmptyList { name: attr.name_or_empty() } } else if matches!( diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 30dd3e4d0..2357b0aad 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -12,7 +12,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; @@ -148,7 +148,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { [missing_primary, ref missing_secondary @ ..] => { let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); - let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg); + let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, msg); // If multiple feature gates would be required to enable this expression, include // them as help messages. Don't emit a separate error for each missing feature gate. @@ -161,7 +161,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { "add `#![feature({})]` to the crate attributes to enable", gate, ); - err.help(¬e); + err.help(note); } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 5cfe691df..7812dcde4 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; @@ -237,6 +237,37 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } + fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) { + let data = self.typeck_results().offset_of_data(); + let &(container, ref indices) = + data.get(expr.hir_id).expect("no offset_of_data for offset_of"); + + let body_did = self.typeck_results().hir_owner.to_def_id(); + let param_env = self.tcx.param_env(body_did); + + let mut current_ty = container; + + for &index in indices { + match current_ty.kind() { + ty::Adt(def, subst) => { + let field = &def.non_enum_variant().fields[index]; + + self.insert_def_id(field.did); + let field_ty = field.ty(self.tcx, subst); + + current_ty = self.tcx.normalize_erasing_regions(param_env, field_ty); + } + // we don't need to mark tuple fields as live, + // but we may need to mark subfields + ty::Tuple(tys) => { + current_ty = + self.tcx.normalize_erasing_regions(param_env, tys[index.as_usize()]); + } + _ => span_bug!(expr.span, "named field access on non-ADT"), + } + } + } + fn mark_live_symbols(&mut self) { let mut scanned = LocalDefIdSet::default(); while let Some(id) = self.worklist.pop() { @@ -405,6 +436,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { hir::ExprKind::Closure(cls) => { self.insert_def_id(cls.def_id.to_def_id()); } + hir::ExprKind::OffsetOf(..) => { + self.handle_offset_of(expr); + } _ => (), } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 9dd39a5c9..3483f7da5 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -1,61 +1,69 @@ //! Detecting usage of the `#[debugger_visualizer]` attribute. -use hir::CRATE_HIR_ID; -use rustc_data_structures::fx::FxHashSet; +use rustc_ast::Attribute; +use rustc_data_structures::sync::Lrc; use rustc_expand::base::resolve_path; -use rustc_hir as hir; -use rustc_hir::HirId; -use rustc_middle::ty::TyCtxt; -use rustc_middle::{query::LocalCrate, ty::query::Providers}; -use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType}; +use rustc_middle::{ + middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}, + query::{LocalCrate, Providers}, + ty::TyCtxt, +}; +use rustc_session::Session; +use rustc_span::sym; -use std::sync::Arc; +use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable}; -use crate::errors::DebugVisualizerUnreadable; - -fn check_for_debugger_visualizer( - tcx: TyCtxt<'_>, - hir_id: HirId, - debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>, -) { - let attrs = tcx.hir().attrs(hir_id); - for attr in attrs { +impl DebuggerVisualizerCollector<'_> { + fn check_for_debugger_visualizer(&mut self, attr: &Attribute) { if attr.has_name(sym::debugger_visualizer) { - let Some(list) = attr.meta_item_list() else { - continue + let Some(hints) = attr.meta_item_list() else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let meta_item = match list.len() { - 1 => match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => continue, - }, - _ => continue, + let hint = if hints.len() == 1 { + &hints[0] + } else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let visualizer_type = match meta_item.name_or_empty() { - sym::natvis_file => DebuggerVisualizerType::Natvis, - sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter, - _ => continue, + let Some(meta_item) = hint.meta_item() else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let file = match meta_item.value_str() { - Some(value) => { - match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) { - Ok(file) => file, - _ => continue, + let (visualizer_type, visualizer_path) = + match (meta_item.name_or_empty(), meta_item.value_str()) { + (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value), + (sym::gdb_script_file, Some(value)) => { + (DebuggerVisualizerType::GdbPrettyPrinter, value) } - } - None => continue, - }; + (_, _) => { + self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span }); + return; + } + }; + + let file = + match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) { + Ok(file) => file, + Err(mut err) => { + err.emit(); + return; + } + }; match std::fs::read(&file) { Ok(contents) => { - debugger_visualizers - .insert(DebuggerVisualizerFile::new(Arc::from(contents), visualizer_type)); + self.visualizers.push(DebuggerVisualizerFile::new( + Lrc::from(contents), + visualizer_type, + file, + )); } Err(error) => { - tcx.sess.emit_err(DebugVisualizerUnreadable { + self.sess.emit_err(DebugVisualizerUnreadable { span: meta_item.span, file: &file, error, @@ -66,29 +74,30 @@ fn check_for_debugger_visualizer( } } -/// Traverses and collects the debugger visualizers for a specific crate. -fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> { - // Initialize the collector. - let mut debugger_visualizers = FxHashSet::default(); +struct DebuggerVisualizerCollector<'a> { + sess: &'a Session, + visualizers: Vec<DebuggerVisualizerFile>, +} - // Collect debugger visualizers in this crate. - tcx.hir().for_each_module(|id| { - check_for_debugger_visualizer( - tcx, - tcx.hir().local_def_id_to_hir_id(id), - &mut debugger_visualizers, - ) - }); +impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { + fn visit_attribute(&mut self, attr: &'ast Attribute) { + self.check_for_debugger_visualizer(attr); + rustc_ast::visit::walk_attribute(self, attr); + } +} - // Collect debugger visualizers on the crate attributes. - check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers); +/// Traverses and collects the debugger visualizers for a specific crate. +fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> { + let resolver_and_krate = tcx.resolver_for_lowering(()).borrow(); + let krate = &*resolver_and_krate.1; - // Extract out the found debugger_visualizer items. - let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>(); + let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; + rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate); - // Sort the visualizers so we always get a deterministic query result. - visualizers.sort(); - visualizers + // We are collecting visualizers in AST-order, which is deterministic, + // so we don't need to do any explicit sorting in order to get a + // deterministic query result + visitor.visualizers } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index eb6ea673c..d8b9f4fae 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -13,7 +13,7 @@ use rustc_ast as ast; use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_hir::OwnerId; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index e3e4b73ef..ffd8f77b7 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -4,7 +4,7 @@ use rustc_errors::error_code; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{ItemId, Node, CRATE_HIR_ID}; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{sigpipe, CrateType, EntryFnType}; use rustc_session::parse::feature_err; diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 139ba8c96..99fc69d1b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,7 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan, + error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed, + IntoDiagnostic, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1355,8 +1356,8 @@ pub enum AttrApplication { #[label] span: Span, }, - #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")] - StructEnumFunctionUnion { + #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")] + StructEnumFunctionMethodUnion { #[primary_span] hint_span: Span, #[label] @@ -1555,3 +1556,160 @@ pub struct SkippingConstChecks { #[primary_span] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(passes_unreachable_due_to_uninhabited)] +pub struct UnreachableDueToUninhabited<'desc, 'tcx> { + pub descr: &'desc str, + #[label] + pub expr: Span, + #[label(passes_label_orig)] + #[note] + pub orig: Span, + pub ty: Ty<'tcx>, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_maybe_capture_ref)] +#[help] +pub struct UnusedVarMaybeCaptureRef { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_capture_maybe_capture_ref)] +#[help] +pub struct UnusedCaptureMaybeCaptureRef { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_remove_field)] +pub struct UnusedVarRemoveField { + pub name: String, + #[subdiagnostic] + pub sugg: UnusedVarRemoveFieldSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + passes_unused_var_remove_field_suggestion, + applicability = "machine-applicable" +)] +pub struct UnusedVarRemoveFieldSugg { + #[suggestion_part(code = "")] + pub spans: Vec<Span>, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_assigned_only)] +#[note] +pub struct UnusedVarAssignedOnly { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unnecessary_stable_feature)] +pub struct UnnecessaryStableFeature { + pub feature: Symbol, + pub since: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unnecessary_partial_stable_feature)] +pub struct UnnecessaryPartialStableFeature { + #[suggestion(code = "{implies}", applicability = "maybe-incorrect")] + pub span: Span, + #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")] + pub line: Span, + pub feature: Symbol, + pub since: Symbol, + pub implies: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(passes_ineffective_unstable_impl)] +#[note] +pub struct IneffectiveUnstableImpl; + +#[derive(LintDiagnostic)] +#[diag(passes_unused_assign)] +#[help] +pub struct UnusedAssign { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_assign_passed)] +#[help] +pub struct UnusedAssignPassed { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_variable_try_prefix)] +pub struct UnusedVariableTryPrefix { + #[label] + pub label: Option<Span>, + #[subdiagnostic] + pub string_interp: Vec<UnusedVariableStringInterp>, + #[subdiagnostic] + pub sugg: UnusedVariableTryPrefixSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +pub struct UnusedVariableTryPrefixSugg { + #[suggestion_part(code = "_{name}")] + pub spans: Vec<Span>, + pub name: String, +} + +pub struct UnusedVariableStringInterp { + pub lit: Span, + pub lo: Span, + pub hi: Span, +} + +impl AddToDiagnostic for UnusedVariableStringInterp { + fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) { + diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); + diag.multipart_suggestion( + crate::fluent_generated::passes_string_interpolation_only_works, + vec![(self.lo, String::from("format!(")), (self.hi, String::from(")"))], + Applicability::MachineApplicable, + ); + } +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_variable_try_ignore)] +pub struct UnusedVarTryIgnore { + #[subdiagnostic] + pub sugg: UnusedVarTryIgnoreSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +pub struct UnusedVarTryIgnoreSugg { + #[suggestion_part(code = "{name}: _")] + pub shorthands: Vec<Span>, + #[suggestion_part(code = "_")] + pub non_shorthands: Vec<Span>, + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_attr_crate_level)] +#[note] +pub struct AttrCrateLevelOnly { + #[subdiagnostic] + pub sugg: Option<AttrCrateLevelOnlySugg>, +} + +#[derive(Subdiagnostic)] +#[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")] +pub struct AttrCrateLevelOnlySugg { + #[primary_span] + pub attr: Span, +} diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 3942a73be..363e17436 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -31,7 +31,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); + tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, message); } } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 47e032758..dc5e45407 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -302,7 +302,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { [ ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps, Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, - Path, AddrOf, Break, Continue, Ret, InlineAsm, Struct, Repeat, Yield, Err + Path, AddrOf, Break, Continue, Ret, InlineAsm, OffsetOf, Struct, Repeat, Yield, + Err ] ); hir_visit::walk_expr(self, e) @@ -568,7 +569,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, - InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err + InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err ] ); ast_visit::walk_expr(self, e) diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index fdd0e5dab..476394f30 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::cstore::ExternCrate; use rustc_span::{symbol::kw::Empty, Span}; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; pub(crate) enum Duplicate { Plain, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index b7e07aff4..0da4b2946 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,6 +12,8 @@ #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "256"] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -19,8 +21,8 @@ extern crate rustc_middle; extern crate tracing; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; -use rustc_middle::ty::query::Providers; +use rustc_fluent_macro::fluent_messages; +use rustc_middle::query::Providers; mod check_attr; mod check_const; diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index f4da1aaec..44174b1b8 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -9,7 +9,7 @@ use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER}; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::LibFeatures; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use rustc_span::{sym, Span}; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index a8471ce3b..63b1578d4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -81,23 +81,24 @@ //! We generate various special nodes for various, well, special purposes. //! These are described in the `Liveness` struct. +use crate::errors; + use self::LiveNodeKind::*; use self::VarKind::*; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::Applicability; -use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::*; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet}; -use rustc_index::vec::IndexVec; -use rustc_middle::ty::query::Providers; +use rustc_index::IndexVec; +use rustc_middle::query::Providers; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::DUMMY_SP; use rustc_span::{BytePos, Span}; use std::collections::VecDeque; @@ -137,14 +138,9 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { } } -fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) { - let local_def_id = match def_id.as_local() { - None => return, - Some(def_id) => def_id, - }; - +fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Don't run unused pass for #[derive()] - let parent = tcx.local_parent(local_def_id); + let parent = tcx.local_parent(def_id); if let DefKind::Impl { .. } = tcx.def_kind(parent) && tcx.has_attr(parent, sym::automatically_derived) { @@ -152,12 +148,12 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) { } // Don't run unused pass for #[naked] - if tcx.has_attr(def_id, sym::naked) { + if tcx.has_attr(def_id.to_def_id(), sym::naked) { return; } let mut maps = IrMaps::new(tcx); - let body_id = tcx.hir().body_owned_by(local_def_id); + let body_id = tcx.hir().body_owned_by(def_id); let hir_id = tcx.hir().body_owner(body_id); let body = tcx.hir().body(body_id); @@ -173,7 +169,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) { maps.visit_body(body); // compute liveness - let mut lsets = Liveness::new(&mut maps, local_def_id); + let mut lsets = Liveness::new(&mut maps, def_id); let entry_ln = lsets.compute(&body, hir_id); lsets.log_liveness(entry_ln, body_id.hir_id); @@ -331,7 +327,7 @@ impl<'tcx> IrMaps<'tcx> { pats.extend(inner_pat.iter()); } Struct(_, fields, _) => { - let (short, not_short): (Vec<_>, _) = + let (short, not_short): (Vec<hir::PatField<'_>>, _) = fields.iter().partition(|f| f.is_shorthand); shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id)); pats.extend(not_short.iter().map(|f| f.pat)); @@ -473,6 +469,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::InlineAsm(..) + | hir::ExprKind::OffsetOf(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err(_) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) @@ -591,8 +588,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> bool { - let successor = self.successors[ln].unwrap(); - self.assigned_on_entry(successor, var) + match self.successors[ln] { + Some(successor) => self.assigned_on_entry(successor, var), + None => { + self.ir.tcx.sess.delay_span_bug(DUMMY_SP, "no successor"); + true + } + } } fn write_vars<F>(&self, wr: &mut dyn Write, mut test: F) -> io::Result<()> @@ -1129,7 +1131,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Err(_) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) - | hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ, + | hir::ExprKind::Path(hir::QPath::LangItem(..)) + | hir::ExprKind::OffsetOf(..) => succ, // Note that labels have been resolved, so we don't need to look // at the label ident @@ -1294,13 +1297,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.exit_ln } - fn warn_about_unreachable( + fn warn_about_unreachable<'desc>( &mut self, orig_span: Span, orig_ty: Ty<'tcx>, expr_span: Span, expr_id: HirId, - descr: &str, + descr: &'desc str, ) { if !orig_ty.is_never() { // Unreachable code warnings are already emitted during type checking. @@ -1313,22 +1316,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // that we do not emit the same warning twice if the uninhabited type // is indeed `!`. - let msg = format!("unreachable {}", descr); - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNREACHABLE_CODE, expr_id, expr_span, - &msg, - |diag| { - diag.span_label(expr_span, &msg) - .span_label(orig_span, "any code following this expression is unreachable") - .span_note( - orig_span, - &format!( - "this expression has type `{}`, which is uninhabited", - orig_ty - ), - ) + errors::UnreachableDueToUninhabited { + expr: expr_span, + orig: orig_span, + descr, + ty: orig_ty, }, ); } @@ -1418,6 +1414,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) + | hir::ExprKind::OffsetOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Closure { .. } @@ -1479,23 +1476,21 @@ impl<'tcx> Liveness<'_, 'tcx> { if self.used_on_entry(entry_ln, var) { if !self.live_on_entry(entry_ln, var) { if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_ASSIGNMENTS, var_hir_id, vec![span], - format!("value captured by `{}` is never read", name), - |lint| lint.help("did you mean to capture by reference instead?"), + errors::UnusedCaptureMaybeCaptureRef { name }, ); } } } else { if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, var_hir_id, vec![span], - format!("unused variable: `{}`", name), - |lint| lint.help("did you mean to capture by reference instead?"), + errors::UnusedVarMaybeCaptureRef { name }, ); } } @@ -1510,11 +1505,14 @@ impl<'tcx> Liveness<'_, 'tcx> { Some(entry_ln), Some(body), |spans, hir_id, ln, var| { - if !self.live_on_entry(ln, var) { - self.report_unused_assign(hir_id, spans, var, |name| { - format!("value passed to `{}` is never read", name) - }); - } + if !self.live_on_entry(ln, var) + && let Some(name) = self.should_warn(var) { + self.ir.tcx.emit_spanned_lint( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + errors::UnusedAssignPassed { name }, + ); } }, ); } @@ -1583,39 +1581,35 @@ impl<'tcx> Liveness<'_, 'tcx> { if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) }; if is_assigned { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .into_iter() .map(|(_, _, ident_span)| ident_span) .collect::<Vec<_>>(), - format!("variable `{}` is assigned to, but never used", name), - |lint| lint.note(&format!("consider using `_{}` instead", name)), + errors::UnusedVarAssignedOnly { name }, ) } else if can_remove { - self.ir.tcx.struct_span_lint_hir( + let spans = hir_ids_and_spans + .iter() + .map(|(_, pat_span, _)| { + let span = self + .ir + .tcx + .sess + .source_map() + .span_extend_to_next_char(*pat_span, ',', true); + span.with_hi(BytePos(span.hi().0 + 1)) + }) + .collect(); + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(), - format!("unused variable: `{}`", name), - |lint| { - lint.multipart_suggestion( - "try removing the field", - hir_ids_and_spans - .iter() - .map(|(_, pat_span, _)| { - let span = self - .ir - .tcx - .sess - .source_map() - .span_extend_to_next_char(*pat_span, ',', true); - (span.with_hi(BytePos(span.hi().0 + 1)), String::new()) - }) - .collect(), - Applicability::MachineApplicable, - ) + errors::UnusedVarRemoveField { + name, + sugg: errors::UnusedVarRemoveFieldSugg { spans }, }, ); } else { @@ -1629,55 +1623,46 @@ impl<'tcx> Liveness<'_, 'tcx> { // the field" message, and suggest `_` for the non-shorthands. If we only // have non-shorthand, then prefix with an underscore instead. if !shorthands.is_empty() { - let shorthands = shorthands - .into_iter() - .map(|(_, pat_span, _)| (pat_span, format!("{}: _", name))) - .chain( - non_shorthands - .into_iter() - .map(|(_, pat_span, _)| (pat_span, "_".to_string())), - ) - .collect::<Vec<_>>(); + let shorthands = + shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect(); + let non_shorthands = + non_shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect(); - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .iter() .map(|(_, pat_span, _)| *pat_span) .collect::<Vec<_>>(), - format!("unused variable: `{}`", name), - |lint| { - lint.multipart_suggestion( - "try ignoring the field", + errors::UnusedVarTryIgnore { + sugg: errors::UnusedVarTryIgnoreSugg { shorthands, - Applicability::MachineApplicable, - ) + non_shorthands, + name, + }, }, ); } else { let non_shorthands = non_shorthands .into_iter() - .map(|(_, _, ident_span)| (ident_span, format!("_{}", name))) + .map(|(_, _, ident_span)| ident_span) .collect::<Vec<_>>(); - - self.ir.tcx.struct_span_lint_hir( + let suggestions = self.string_interp_suggestions(&name, opt_body); + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .iter() .map(|(_, _, ident_span)| *ident_span) .collect::<Vec<_>>(), - format!("unused variable: `{}`", name), - |lint| { - if self.has_added_lit_match_name_span(&name, opt_body, lint) { - lint.span_label(pat.span, "unused variable"); - } - lint.multipart_suggestion( - "if this is intentional, prefix it with an underscore", - non_shorthands, - Applicability::MachineApplicable, - ) + errors::UnusedVariableTryPrefix { + label: if !suggestions.is_empty() { Some(pat.span) } else { None }, + sugg: errors::UnusedVariableTryPrefixSugg { + spans: non_shorthands, + name, + }, + string_interp: suggestions, }, ); } @@ -1685,65 +1670,40 @@ impl<'tcx> Liveness<'_, 'tcx> { } } - fn has_added_lit_match_name_span( + fn string_interp_suggestions( &self, name: &str, opt_body: Option<&hir::Body<'_>>, - err: &mut Diagnostic, - ) -> bool { - let mut has_litstring = false; - let Some(opt_body) = opt_body else {return false;}; + ) -> Vec<errors::UnusedVariableStringInterp> { + let mut suggs = Vec::new(); + let Some(opt_body) = opt_body else { return suggs; }; let mut visitor = CollectLitsVisitor { lit_exprs: vec![] }; intravisit::walk_body(&mut visitor, opt_body); for lit_expr in visitor.lit_exprs { let hir::ExprKind::Lit(litx) = &lit_expr.kind else { continue }; let rustc_ast::LitKind::Str(syb, _) = litx.node else{ continue; }; let name_str: &str = syb.as_str(); - let mut name_pa = String::from("{"); - name_pa.push_str(&name); - name_pa.push('}'); + let name_pa = format!("{{{name}}}"); if name_str.contains(&name_pa) { - err.span_label( - lit_expr.span, - "you might have meant to use string interpolation in this string literal", - ); - err.multipart_suggestion( - "string interpolation only works in `format!` invocations", - vec![ - (lit_expr.span.shrink_to_lo(), "format!(".to_string()), - (lit_expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - has_litstring = true; + suggs.push(errors::UnusedVariableStringInterp { + lit: lit_expr.span, + lo: lit_expr.span.shrink_to_lo(), + hi: lit_expr.span.shrink_to_hi(), + }); } } - has_litstring + suggs } fn warn_about_dead_assign(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) { - if !self.live_on_exit(ln, var) { - self.report_unused_assign(hir_id, spans, var, |name| { - format!("value assigned to `{}` is never read", name) - }); - } - } - - fn report_unused_assign( - &self, - hir_id: HirId, - spans: Vec<Span>, - var: Variable, - message: impl Fn(&str) -> String, - ) { - if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( - lint::builtin::UNUSED_ASSIGNMENTS, - hir_id, - spans, - message(&name), - |lint| lint.help("maybe it is overwritten before being read?"), - ) - } + if !self.live_on_exit(ln, var) + && let Some(name) = self.should_warn(var) { + self.ir.tcx.emit_spanned_lint( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + errors::UnusedAssign { name }, + ); + } } } diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index b4cf19e4a..73cfe68e7 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -6,7 +6,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Destination, Movability, Node}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index c398467f0..a849d61ed 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -6,7 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind}; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; use rustc_span::symbol::sym; @@ -203,6 +203,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> { | ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) + | ExprKind::OffsetOf(..) | ExprKind::Struct(..) | ExprKind::Repeat(..) | ExprKind::Yield(..) => { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index a5f7b07fe..160528e40 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -13,7 +13,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::CrateType; use rustc_target::spec::abi::Abi; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4a35c6794..b81b7ad60 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -7,7 +7,6 @@ use rustc_attr::{ UnstableReason, VERSION_PLACEHOLDER, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -17,7 +16,8 @@ use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index}; -use rustc_middle::ty::{query::Providers, TyCtxt}; +use rustc_middle::query::Providers; +use rustc_middle::ty::TyCtxt; use rustc_session::lint; use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED}; use rustc_span::symbol::{sym, Symbol}; @@ -554,10 +554,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { let is_const = self.tcx.is_const_fn(def_id.to_def_id()) || self.tcx.is_const_trait_impl_raw(def_id.to_def_id()); - let is_stable = self - .tcx - .lookup_stability(def_id) - .map_or(false, |stability| stability.level.is_stable()); + let is_stable = + self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable()); let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); let is_reachable = self.effective_visibilities.is_reachable(def_id); @@ -759,12 +757,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // do not lint when the trait isn't resolved, since resolution error should // be fixed first if t.path.res != Res::Err && c.fully_stable { - self.tcx.struct_span_lint_hir( + self.tcx.emit_spanned_lint( INEFFECTIVE_UNSTABLE_TRAIT_IMPL, item.hir_id(), span, - "an `#[unstable]` annotation here has no effect", - |lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information") + errors::IneffectiveUnstableImpl, ); } } @@ -773,7 +770,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // needs to have an error emitted. if features.const_trait_impl && *constness == hir::Constness::Const - && const_stab.map_or(false, |(stab, _)| stab.is_const_stable()) + && const_stab.is_some_and(|(stab, _)| stab.is_const_stable()) { self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span }); } @@ -810,15 +807,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { ); let is_allowed_through_unstable_modules = |def_id| { - self.tcx - .lookup_stability(def_id) - .map(|stab| match stab.level { - StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { - allowed_through_unstable_modules - } - _ => false, - }) - .unwrap_or(false) + self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level { + StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { + allowed_through_unstable_modules + } + _ => false, + }) }; if item_is_allowed && !is_allowed_through_unstable_modules(def_id) { @@ -1095,29 +1089,16 @@ fn unnecessary_partially_stable_feature_lint( implies: Symbol, since: Symbol, ) { - tcx.struct_span_lint_hir( + tcx.emit_spanned_lint( lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, - format!( - "the feature `{feature}` has been partially stabilized since {since} and is succeeded \ - by the feature `{implies}`" - ), - |lint| { - lint.span_suggestion( - span, - &format!( - "if you are using features which are still unstable, change to using `{implies}`" - ), - implies, - Applicability::MaybeIncorrect, - ) - .span_suggestion( - tcx.sess.source_map().span_extend_to_line(span), - "if you are using features which are now stable, remove this line", - "", - Applicability::MaybeIncorrect, - ) + errors::UnnecessaryPartialStableFeature { + span, + line: tcx.sess.source_map().span_extend_to_line(span), + feature, + since, + implies, }, ); } @@ -1131,7 +1112,10 @@ fn unnecessary_stable_feature_lint( if since.as_str() == VERSION_PLACEHOLDER { since = rust_version_symbol(); } - tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| { - lint - }); + tcx.emit_spanned_lint( + lint::builtin::STABLE_FEATURES, + hir::CRATE_HIR_ID, + span, + errors::UnnecessaryStableFeature { feature, since }, + ); } diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 605cf0a93..d87df706c 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self, HirId}; -use rustc_middle::ty::query::Providers; +use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::Span; |