diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 234 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/input_stats.rs | 61 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 1 |
5 files changed, 207 insertions, 140 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c2a58b4cd7d..1b965b9545c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,7 +9,7 @@ use std::cell::Cell; use std::collections::hash_map::Entry; use rustc_abi::{Align, ExternAbi, Size}; -use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast}; +use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast}; use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; @@ -30,11 +30,13 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; +use rustc_session::lint; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; +use rustc_span::edition::Edition; use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; @@ -118,6 +120,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { let mut style = None; match attr { + Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch { + span: attr_span, + .. + }) => { + self.check_must_be_applied_to_trait(*attr_span, span, target); + } Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => { self.check_confusables(*first_span, target); } @@ -132,6 +140,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Optimize(_, attr_span)) => { self.check_optimize(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::LoopMatch(attr_span)) => { + self.check_loop_match(hir_id, *attr_span, target) + } + Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { + self.check_const_continue(hir_id, *attr_span, target) + } Attribute::Parsed(AttributeKind::AllowInternalUnstable(syms)) => self .check_allow_internal_unstable( hir_id, @@ -150,19 +164,34 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */ } - + Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { + self.check_object_lifetime_default(hir_id); + } &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => { self.check_rustc_pub_transparent(attr_span, span, attrs) } Attribute::Parsed(AttributeKind::Cold(attr_span)) => { self.check_cold(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { + self.check_export_name(hir_id, *attr_span, span, target) + } Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { self.check_align(span, target, *align, *repr_span) } + Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => { + self.check_link_section(hir_id, *attr_span, span, target) + } Attribute::Parsed(AttributeKind::Naked(attr_span)) => { self.check_naked(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => { + self.check_track_caller(hir_id, *attr_span, attrs, span, target) + } + Attribute::Parsed( + AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span) + | AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span), + ) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target), Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -171,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => { + self.check_link_name(hir_id, *attr_span, *name, span, target) + } Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { self.check_may_dangle(hir_id, *attr_span) } @@ -180,6 +212,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::NoMangle(attr_span)) => { self.check_no_mangle(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => { + self.check_used(*attr_span, target, span); + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -199,9 +234,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_target_feature(hir_id, attr, span, target, attrs) } [sym::thread_local, ..] => self.check_thread_local(attr, span, target), - [sym::track_caller, ..] => { - self.check_track_caller(hir_id, attr.span(), attrs, span, target) - } [sym::doc, ..] => self.check_doc_attrs( attr, attr_item.style, @@ -211,11 +243,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &mut doc_aliases, ), [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), - [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target), - [sym::rustc_layout_scalar_valid_range_start, ..] - | [sym::rustc_layout_scalar_valid_range_end, ..] => { - self.check_rustc_layout_scalar_valid_range(attr, span, target) - } [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), [sym::rustc_std_internal_symbol, ..] => { self.check_rustc_std_internal_symbol(attr, span, target) @@ -250,7 +277,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_must_implement_one_of, ..] | [sym::rustc_deny_explicit_impl, ..] | [sym::rustc_do_not_implement_via_object, ..] - | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), + | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target), [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), @@ -264,8 +291,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), - [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target), - [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) } @@ -280,7 +305,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::no_implicit_prelude, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Mod) } - [sym::rustc_object_lifetime_default, ..] => self.check_object_lifetime_default(hir_id), [sym::proc_macro, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) } @@ -317,7 +341,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfi_encoding // FIXME(cfi_encoding) | sym::pointee // FIXME(derive_coerce_pointee) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) - | sym::used // handled elsewhere to restrict to static items | sym::instruction_set // broken on stable!!! | sym::windows_subsystem // broken on stable!!! | sym::patchable_function_entry // FIXME(patchable_function_entry) @@ -387,8 +410,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } self.check_repr(attrs, span, target, item, hir_id); - self.check_used(attrs, target, span); self.check_rustc_force_inline(hir_id, attrs, span, target); + self.check_mix_no_mangle_export(hir_id, attrs); } fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) { @@ -716,9 +739,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - for attr in attrs { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "track_caller"); - } + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "track_caller"); } _ => { self.dcx().emit_err(errors::TrackedCallerWrongLocation { @@ -1588,7 +1609,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[link_name]` is applied to an item other than a foreign function or static. - fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_link_name( + &self, + hir_id: HirId, + attr_span: Span, + name: Symbol, + span: Span, + target: Target, + ) { match target { Target::ForeignFn | Target::ForeignStatic => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an @@ -1596,27 +1624,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_name"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_name"); } _ => { - // FIXME: #[cold] was previously allowed on non-functions/statics and some crates + // FIXME: #[link_name] was previously allowed on non-functions/statics and some crates // used this, so only emit a warning. - let attr_span = matches!(target, Target::ForeignMod).then_some(attr.span()); - if let Some(s) = attr.value_str() { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span(), - errors::LinkName { span, attr_span, value: s.as_str() }, - ); - } else { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span(), - errors::LinkName { span, attr_span, value: "..." }, - ); - }; + let help_span = matches!(target, Target::ForeignMod).then_some(attr_span); + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr_span, + errors::LinkName { span, help_span, value: name.as_str() }, + ); } } } @@ -1643,7 +1662,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[export_name]` is applied to a function or static. - fn check_export_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_export_name(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Static | Target::Fn => {} Target::Method(..) if self.is_impl_item(hir_id) => {} @@ -1652,32 +1671,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "export_name"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "export_name"); } _ => { - self.dcx().emit_err(errors::ExportName { attr_span: attr.span(), span }); + self.dcx().emit_err(errors::ExportName { attr_span, span }); } } } - fn check_rustc_layout_scalar_valid_range(&self, attr: &Attribute, span: Span, target: Target) { + fn check_rustc_layout_scalar_valid_range(&self, attr_span: Span, span: Span, target: Target) { if target != Target::Struct { - self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct { - attr_span: attr.span(), - span, - }); + self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct { attr_span, span }); return; } - - let Some(list) = attr.meta_item_list() else { - return; - }; - - if !matches!(&list[..], &[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) { - self.tcx - .dcx() - .emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span() }); - } } /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. @@ -1805,20 +1811,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the attribute is applied to a trait. - fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) { + fn check_must_be_applied_to_trait(&self, attr_span: Span, defn_span: Span, target: Target) { match target { Target::Trait => {} _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { - attr_span: attr.span(), - defn_span: span, - }); + self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span }); } } } /// Checks if `#[link_section]` is applied to a function or static. - fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_link_section(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Static | Target::Fn | Target::Method(..) => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an @@ -1826,7 +1829,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_section"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_section"); } _ => { // FIXME: #[link_section] was previously allowed on non-functions/statics and some @@ -1834,7 +1837,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::LinkSection { span }, ); } @@ -2095,44 +2098,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) { - let mut used_linker_span = None; - let mut used_compiler_span = None; - for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) { - if target != Target::Static { - self.dcx().emit_err(errors::UsedStatic { - attr_span: attr.span(), - span: target_span, - target: target.name(), - }); - } - let inner = attr.meta_item_list(); - match inner.as_deref() { - Some([item]) if item.has_name(sym::linker) => { - if used_linker_span.is_none() { - used_linker_span = Some(attr.span()); - } - } - Some([item]) if item.has_name(sym::compiler) => { - if used_compiler_span.is_none() { - used_compiler_span = Some(attr.span()); - } - } - Some(_) => { - // This error case is handled in rustc_hir_analysis::collect. - } - None => { - // Default case (compiler) when arg isn't defined. - if used_compiler_span.is_none() { - used_compiler_span = Some(attr.span()); - } - } - } - } - if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) { - self.tcx - .dcx() - .emit_err(errors::UsedCompilerLinker { spans: vec![linker_span, compiler_span] }); + fn check_used(&self, attr_span: Span, target: Target, target_span: Span) { + if target != Target::Static { + self.dcx().emit_err(errors::UsedStatic { + attr_span, + span: target_span, + target: target.name(), + }); } } @@ -2619,6 +2591,36 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + fn check_mix_no_mangle_export(&self, hir_id: HirId, attrs: &[Attribute]) { + if let Some(export_name_span) = find_attr!(attrs, AttributeKind::ExportName { span: export_name_span, .. } => *export_name_span) + && let Some(no_mangle_span) = + find_attr!(attrs, AttributeKind::NoMangle(no_mangle_span) => *no_mangle_span) + { + let no_mangle_attr = if no_mangle_span.edition() >= Edition::Edition2024 { + "#[unsafe(no_mangle)]" + } else { + "#[no_mangle]" + }; + let export_name_attr = if export_name_span.edition() >= Edition::Edition2024 { + "#[unsafe(export_name)]" + } else { + "#[export_name]" + }; + + self.tcx.emit_node_span_lint( + lint::builtin::UNUSED_ATTRIBUTES, + hir_id, + no_mangle_span, + errors::MixedExportNameAndNoMangle { + no_mangle_span, + export_name_span, + no_mangle_attr, + export_name_attr, + }, + ); + } + } + /// Checks if `#[autodiff]` is applied to an item other than a function item. fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) { debug!("check_autodiff"); @@ -2630,6 +2632,32 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } + + fn check_loop_match(&self, hir_id: HirId, attr_span: Span, target: Target) { + let node_span = self.tcx.hir_span(hir_id); + + if !matches!(target, Target::Expression) { + self.dcx().emit_err(errors::LoopMatchAttr { attr_span, node_span }); + return; + } + + if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Loop(..)) { + self.dcx().emit_err(errors::LoopMatchAttr { attr_span, node_span }); + }; + } + + fn check_const_continue(&self, hir_id: HirId, attr_span: Span, target: Target) { + let node_span = self.tcx.hir_span(hir_id); + + if !matches!(target, Target::Expression) { + self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span }); + return; + } + + if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Break(..)) { + self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span }); + }; + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { @@ -2804,7 +2832,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { .find(|item| !item.span.is_dummy()) // Skip prelude `use`s .map(|item| errors::ItemFollowingInnerAttr { span: if let Some(ident) = item.kind.ident() { ident.span } else { item.span }, - kind: item.kind.descr(), + kind: tcx.def_descr(item.owner_id.to_def_id()), }); let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel { span, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 4738036318d..ce43b2c281d 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1056,7 +1056,7 @@ impl<'tcx> DeadVisitor<'tcx> { maybe_enum.variants().iter().find(|i| i.name == dead_item.name) { Some(crate::errors::EnumVariantSameName { - descr: tcx.def_descr(dead_item.def_id.to_def_id()), + dead_descr: tcx.def_descr(dead_item.def_id.to_def_id()), dead_name: dead_item.name, variant_span: tcx.def_span(variant.def_id), }) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 94c8ae77ed7..d4988277073 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -31,6 +31,36 @@ pub(crate) struct AutoDiffAttr { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_loop_match_attr)] +pub(crate) struct LoopMatchAttr { + #[primary_span] + pub attr_span: Span, + #[label] + pub node_span: Span, +} + +#[derive(Diagnostic)] +#[diag(passes_const_continue_attr)] +pub(crate) struct ConstContinueAttr { + #[primary_span] + pub attr_span: Span, + #[label] + pub node_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(passes_mixed_export_name_and_no_mangle)] +pub(crate) struct MixedExportNameAndNoMangle { + #[label] + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub no_mangle_span: Span, + #[note] + pub export_name_span: Span, + pub no_mangle_attr: &'static str, + pub export_name_attr: &'static str, +} + #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] pub(crate) struct OuterCrateLevelAttr; @@ -472,7 +502,7 @@ pub(crate) struct Link { #[warning] pub(crate) struct LinkName<'a> { #[help] - pub attr_span: Option<Span>, + pub help_span: Option<Span>, #[label] pub span: Span, pub value: &'a str, @@ -506,13 +536,6 @@ pub(crate) struct RustcLayoutScalarValidRangeNotStruct { } #[derive(Diagnostic)] -#[diag(passes_rustc_layout_scalar_valid_range_arg)] -pub(crate) struct RustcLayoutScalarValidRangeArg { - #[primary_span] - pub attr_span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_only)] pub(crate) struct RustcLegacyConstGenericsOnly { #[primary_span] @@ -612,13 +635,6 @@ pub(crate) struct UsedStatic { } #[derive(Diagnostic)] -#[diag(passes_used_compiler_linker)] -pub(crate) struct UsedCompilerLinker { - #[primary_span] - pub spans: Vec<Span>, -} - -#[derive(Diagnostic)] #[diag(passes_allow_internal_unstable)] pub(crate) struct AllowInternalUnstable { #[primary_span] @@ -1498,7 +1514,7 @@ pub(crate) struct EnumVariantSameName<'tcx> { #[primary_span] pub variant_span: Span, pub dead_name: Symbol, - pub descr: &'tcx str, + pub dead_descr: &'tcx str, } #[derive(Subdiagnostic)] @@ -1696,6 +1712,7 @@ impl Subdiagnostic for UnusedVariableStringInterp { #[derive(LintDiagnostic)] #[diag(passes_unused_variable_try_ignore)] pub(crate) struct UnusedVarTryIgnore { + pub name: String, #[subdiagnostic] pub sugg: UnusedVarTryIgnoreSugg, } diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 46e6c0bf7da..40bc18939d6 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -65,16 +65,16 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) { StatCollector { tcx: Some(tcx), nodes: FxHashMap::default(), seen: FxHashSet::default() }; tcx.hir_walk_toplevel_module(&mut collector); tcx.hir_walk_attributes(&mut collector); - collector.print("HIR STATS", "hir-stats"); + collector.print(tcx, "HIR STATS", "hir-stats"); } -pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) { +pub fn print_ast_stats(tcx: TyCtxt<'_>, krate: &ast::Crate) { use rustc_ast::visit::Visitor; let mut collector = StatCollector { tcx: None, nodes: FxHashMap::default(), seen: FxHashSet::default() }; collector.visit_crate(krate); - collector.print(title, prefix); + collector.print(tcx, "POST EXPANSION AST STATS", "ast-stats"); } impl<'k> StatCollector<'k> { @@ -116,29 +116,48 @@ impl<'k> StatCollector<'k> { } } - fn print(&self, title: &str, prefix: &str) { + fn print(&self, tcx: TyCtxt<'_>, title: &str, prefix: &str) { + use std::fmt::Write; + // We will soon sort, so the initial order does not matter. #[allow(rustc::potential_query_instability)] let mut nodes: Vec<_> = self.nodes.iter().collect(); nodes.sort_by_cached_key(|(label, node)| (node.stats.accum_size(), label.to_owned())); + nodes.reverse(); // bigger items first + + let name_w = 18; + let acc_size1_w = 10; + let acc_size2_w = 8; // " (NN.N%)" + let acc_size_w = acc_size1_w + acc_size2_w; + let count_w = 14; + let item_size_w = 14; + let banner_w = name_w + acc_size_w + count_w + item_size_w; let total_size = nodes.iter().map(|(_, node)| node.stats.accum_size()).sum(); let total_count = nodes.iter().map(|(_, node)| node.stats.count).sum(); - eprintln!("{prefix} {title}"); - eprintln!( - "{} {:<18}{:>18}{:>14}{:>14}", - prefix, "Name", "Accumulated Size", "Count", "Item Size" + // We write all the text into a string and print it with a single + // `eprint!`. This is an attempt to minimize interleaved text if multiple + // rustc processes are printing macro-stats at the same time (e.g. with + // `RUSTFLAGS='-Zinput-stats' cargo build`). It still doesn't guarantee + // non-interleaving, though. + let mut s = String::new(); + _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w)); + _ = writeln!(s, "{prefix} {title}: {}", tcx.crate_name(hir::def_id::LOCAL_CRATE)); + _ = writeln!( + s, + "{prefix} {:<name_w$}{:>acc_size_w$}{:>count_w$}{:>item_size_w$}", + "Name", "Accumulated Size", "Count", "Item Size" ); - eprintln!("{prefix} ----------------------------------------------------------------"); + _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w)); let percent = |m, n| (m * 100) as f64 / n as f64; for (label, node) in nodes { let size = node.stats.accum_size(); - eprintln!( - "{} {:<18}{:>10} ({:4.1}%){:>14}{:>14}", - prefix, + _ = writeln!( + s, + "{prefix} {:<name_w$}{:>acc_size1_w$} ({:4.1}%){:>count_w$}{:>item_size_w$}", label, usize_with_underscores(size), percent(size, total_size), @@ -155,9 +174,9 @@ impl<'k> StatCollector<'k> { for (label, subnode) in subnodes { let size = subnode.accum_size(); - eprintln!( - "{} - {:<18}{:>10} ({:4.1}%){:>14}", - prefix, + _ = writeln!( + s, + "{prefix} - {:<name_w$}{:>acc_size1_w$} ({:4.1}%){:>count_w$}", label, usize_with_underscores(size), percent(size, total_size), @@ -166,15 +185,17 @@ impl<'k> StatCollector<'k> { } } } - eprintln!("{prefix} ----------------------------------------------------------------"); - eprintln!( - "{} {:<18}{:>10} {:>14}", - prefix, + _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w)); + _ = writeln!( + s, + "{prefix} {:<name_w$}{:>acc_size1_w$}{:>acc_size2_w$}{:>count_w$}", "Total", usize_with_underscores(total_size), + "", usize_with_underscores(total_count), ); - eprintln!("{prefix}"); + _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w)); + eprint!("{s}"); } } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 125730377ef..3088e189c20 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1744,6 +1744,7 @@ impl<'tcx> Liveness<'_, 'tcx> { .map(|(_, pat_span, _)| *pat_span) .collect::<Vec<_>>(), errors::UnusedVarTryIgnore { + name: name.clone(), sugg: errors::UnusedVarTryIgnoreSugg { shorthands, non_shorthands, |
