diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 96 | ||||
-rw-r--r-- | compiler/rustc_passes/src/dead.rs | 200 | ||||
-rw-r--r-- | compiler/rustc_passes/src/errors.rs | 79 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_id_validator.rs | 75 | ||||
-rw-r--r-- | compiler/rustc_passes/src/hir_stats.rs | 7 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lang_items.rs | 34 | ||||
-rw-r--r-- | compiler/rustc_passes/src/lib.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 50 | ||||
-rw-r--r-- | compiler/rustc_passes/src/loops.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_passes/src/reachable.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_passes/src/stability.rs | 34 | ||||
-rw-r--r-- | compiler/rustc_passes/src/upvars.rs | 7 | ||||
-rw-r--r-- | compiler/rustc_passes/src/weak_lang_items.rs | 22 |
13 files changed, 344 insertions, 272 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 27a57adf9..2e2874dbc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,7 @@ use crate::errors::{ self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr, OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint, }; -use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; +use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{fluent, Applicability, MultiSpan}; use rustc_expand::base::resolve_path; @@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> { } sym::naked => self.check_naked(hir_id, attr, span, target), sym::rustc_legacy_const_generics => { - self.check_rustc_legacy_const_generics(&attr, span, target, item) + self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item) } sym::rustc_lint_query_instability => { - self.check_rustc_lint_query_instability(&attr, span, target) + self.check_rustc_lint_query_instability(hir_id, &attr, span, target) } sym::rustc_lint_diagnostics => { - self.check_rustc_lint_diagnostics(&attr, span, target) + self.check_rustc_lint_diagnostics(hir_id, &attr, span, target) } sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target), sym::rustc_lint_opt_deny_field_access => { @@ -135,11 +135,13 @@ impl CheckAttrVisitor<'_> { | sym::rustc_dirty | sym::rustc_if_this_changed | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), - sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target), + sym::cmse_nonsecure_entry => { + self.check_cmse_nonsecure_entry(hir_id, attr, span, target) + } sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target), sym::const_trait => self.check_const_trait(attr, span, target), sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), - sym::must_use => self.check_must_use(hir_id, &attr, span, target), + sym::must_use => self.check_must_use(hir_id, &attr, target), sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target), sym::rustc_allow_incoherent_impl => { self.check_allow_incoherent_impl(&attr, span, target) @@ -217,18 +219,6 @@ impl CheckAttrVisitor<'_> { return; } - // FIXME(@lcnr): this doesn't belong here. - if matches!( - target, - Target::Closure - | Target::Fn - | Target::Method(_) - | Target::ForeignFn - | Target::ForeignStatic - ) { - self.tcx.ensure().codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id)); - } - self.check_repr(attrs, span, target, item, hir_id); self.check_used(attrs, target); } @@ -363,7 +353,7 @@ impl CheckAttrVisitor<'_> { attr.span, OnlyHasEffectOn { attr_name: attr.name_or_empty(), - target_name: allowed_target.name().replace(" ", "_"), + target_name: allowed_target.name().replace(' ', "_"), }, ); } @@ -386,6 +376,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -393,7 +384,13 @@ impl CheckAttrVisitor<'_> { } /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. - fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_cmse_nonsecure_entry( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, @@ -401,6 +398,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -413,8 +411,7 @@ impl CheckAttrVisitor<'_> { if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) { for p in generics.params { let hir::GenericParamKind::Type { .. } = p.kind else { continue }; - let param_id = tcx.hir().local_def_id(p.hir_id); - let default = tcx.object_lifetime_default(param_id); + let default = tcx.object_lifetime_default(p.def_id); let repr = match default { ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(), ObjectLifetimeDefault::Static => "'static".to_owned(), @@ -465,9 +462,11 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span }); + self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation { + attr_span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); false } } @@ -576,6 +575,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } @@ -715,7 +715,7 @@ impl CheckAttrVisitor<'_> { if let Some(values) = meta.meta_item_list() { let mut errors = 0; for v in values { - match v.literal() { + match v.lit() { Some(l) => match l.kind { LitKind::Str(s, _) => { if !self.check_doc_alias_value(v, s, hir_id, target, true, aliases) { @@ -1163,17 +1163,7 @@ impl CheckAttrVisitor<'_> { } /// Warns against some misuses of `#[must_use]` - fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { - let node = self.tcx.hir().get(hir_id); - if let Some(kind) = node.fn_kind() && let rustc_hir::IsAsync::Async = kind.asyncness() { - self.tcx.emit_spanned_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::MustUseAsync { span } - ); - } - + fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( target, Target::Fn @@ -1240,7 +1230,7 @@ impl CheckAttrVisitor<'_> { UNUSED_ATTRIBUTES, hir_id, attr.span, - errors::Cold { span }, + errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID }, ); } } @@ -1365,7 +1355,7 @@ impl CheckAttrVisitor<'_> { return false; }; - if matches!(&list[..], &[NestedMetaItem::Literal(Lit { kind: LitKind::Int(..), .. })]) { + if matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) { true } else { self.tcx.sess.emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span }); @@ -1376,6 +1366,7 @@ impl CheckAttrVisitor<'_> { /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, @@ -1386,6 +1377,7 @@ impl CheckAttrVisitor<'_> { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); return false; } @@ -1426,7 +1418,7 @@ impl CheckAttrVisitor<'_> { let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128; let mut invalid_args = vec![]; for meta in list { - if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { + if let Some(LitKind::Int(val, _)) = meta.lit().map(|lit| &lit.kind) { if *val >= arg_count { let span = meta.span(); self.tcx.sess.emit_err(errors::RustcLegacyConstGenericsIndexExceed { @@ -1450,12 +1442,19 @@ impl CheckAttrVisitor<'_> { /// Helper function for checking that the provided attribute is only applied to a function or /// method. - fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_applied_to_fn_or_method( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, }); false } else { @@ -1467,17 +1466,24 @@ impl CheckAttrVisitor<'_> { /// or method. fn check_rustc_lint_query_instability( &self, + hir_id: HirId, attr: &Attribute, span: Span, target: Target, ) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or /// method. - fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool { - self.check_applied_to_fn_or_method(attr, span, target) + fn check_rustc_lint_diagnostics( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. @@ -2131,7 +2137,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn visit_variant(&mut self, variant: &'tcx hir::Variant<'tcx>) { - self.check_attributes(variant.id, variant.span, Target::Variant, None); + self.check_attributes(variant.hir_id, variant.span, Target::Variant, None); intravisit::walk_variant(self, variant) } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 753d01f46..a71ae717a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, Applicability, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -18,7 +18,10 @@ use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; use std::mem; -use crate::errors::UselessAssignment; +use crate::errors::{ + ChangeFieldsToBeOfUnitType, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, + UselessAssignment, +}; // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a @@ -121,7 +124,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) { match self.typeck_results().expr_ty_adjusted(lhs).kind() { ty::Adt(def, _) => { - let index = self.tcx.field_index(hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(hir_id); self.insert_def_id(def.non_enum_variant().fields[index].did); } ty::Tuple(..) => {} @@ -205,7 +208,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let PatKind::Wild = pat.pat.kind { continue; } - let index = self.tcx.field_index(pat.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(pat.hir_id); self.insert_def_id(variant.fields[index].did); } } @@ -338,7 +341,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() { for field in fields { - let index = self.tcx.field_index(field.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(field.hir_id); self.insert_def_id(adt.non_enum_variant().fields[index].did); } } @@ -359,7 +362,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { let has_repr_c = self.repr_has_repr_c; let has_repr_simd = self.repr_has_repr_simd; let live_fields = def.fields().iter().filter_map(|f| { - let def_id = tcx.hir().local_def_id(f.hir_id); + let def_id = f.def_id; if has_repr_c || (f.is_positional() && has_repr_simd) { return Some(def_id); } @@ -430,7 +433,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.in_pat = false; } - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { self.handle_res(path.res); intravisit::walk_path(self, path); } @@ -470,11 +473,6 @@ fn has_allow_dead_code_or_lang_attr_helper( return true; } - // (To be) stable attribute for #[lang = "oom"] - if tcx.sess.contains_name(attrs, sym::alloc_error_handler) { - return true; - } - let def_id = tcx.hir().local_def_id(id); if tcx.def_kind(def_id).has_codegen_attrs() { let cg_attrs = tcx.codegen_fn_attrs(def_id); @@ -524,17 +522,13 @@ fn check_item<'tcx>( DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { - let hir = tcx.hir(); if allow_dead_code { - worklist.extend( - enum_def.variants.iter().map(|variant| hir.local_def_id(variant.id)), - ); + worklist.extend(enum_def.variants.iter().map(|variant| variant.def_id)); } for variant in enum_def.variants { - if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { - struct_constructors - .insert(hir.local_def_id(ctor_hir_id), hir.local_def_id(variant.id)); + if let Some(ctor_def_id) = variant.data.ctor_def_id() { + struct_constructors.insert(ctor_def_id, variant.def_id); } } } @@ -698,99 +692,89 @@ impl<'tcx> DeadVisitor<'tcx> { parent_item: Option<LocalDefId>, is_positional: bool, ) { - if let Some(&first_id) = dead_codes.first() { - let tcx = self.tcx; - let names: Vec<_> = dead_codes - .iter() - .map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string()) - .collect(); - let spans: Vec<_> = dead_codes - .iter() - .map(|&def_id| match tcx.def_ident_span(def_id) { - Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()), - None => tcx.def_span(def_id), + let Some(&first_id) = dead_codes.first() else { + return; + }; + let tcx = self.tcx; + let names: Vec<_> = + dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect(); + let spans: Vec<_> = dead_codes + .iter() + .map(|&def_id| match tcx.def_ident_span(def_id) { + Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()), + None => tcx.def_span(def_id), + }) + .collect(); + + let descr = tcx.def_kind(first_id).descr(first_id.to_def_id()); + let num = dead_codes.len(); + let multiple = num > 6; + let name_list = names.into(); + + let lint = if is_positional { + lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS + } else { + lint::builtin::DEAD_CODE + }; + + let parent_info = if let Some(parent_item) = parent_item { + let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id()); + Some(ParentInfo { + num, + descr, + parent_descr, + span: tcx.def_ident_span(parent_item).unwrap(), + }) + } else { + None + }; + + let encl_def_id = parent_item.unwrap_or(first_id); + let ignored_derived_impls = + if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { + let trait_list = ign_traits + .iter() + .map(|(trait_id, _)| self.tcx.item_name(*trait_id)) + .collect::<Vec<_>>(); + let trait_list_len = trait_list.len(); + Some(IgnoredDerivedImpls { + name: self.tcx.item_name(encl_def_id.to_def_id()), + trait_list: trait_list.into(), + trait_list_len, }) - .collect(); - - let descr = tcx.def_kind(first_id).descr(first_id.to_def_id()); - let span_len = dead_codes.len(); - let names = match &names[..] { - _ if span_len > 6 => String::new(), - [name] => format!("`{name}` "), - [names @ .., last] => { - format!( - "{} and `{last}` ", - names.iter().map(|name| format!("`{name}`")).join(", ") - ) - } - [] => unreachable!(), + } else { + None }; - let msg = format!( - "{these}{descr}{s} {names}{are} never {participle}", - these = if span_len > 6 { "multiple " } else { "" }, - s = pluralize!(span_len), - are = pluralize!("is", span_len), - ); - - tcx.struct_span_lint_hir( - if is_positional { - lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS - } else { - lint::builtin::DEAD_CODE - }, - tcx.hir().local_def_id_to_hir_id(first_id), - MultiSpan::from_spans(spans.clone()), - msg, - |err| { - if is_positional { - err.multipart_suggestion( - &format!( - "consider changing the field{s} to be of unit type to \ - suppress this warning while preserving the field \ - numbering, or remove the field{s}", - s = pluralize!(span_len) - ), - spans.iter().map(|sp| (*sp, "()".to_string())).collect(), - // "HasPlaceholders" because applying this fix by itself isn't - // enough: All constructor calls have to be adjusted as well - Applicability::HasPlaceholders, - ); - } - if let Some(parent_item) = parent_item { - let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id()); - err.span_label( - tcx.def_ident_span(parent_item).unwrap(), - format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)), - ); - } + let diag = if is_positional { + MultipleDeadCodes::UnusedTupleStructFields { + multiple, + num, + descr, + participle, + name_list, + change_fields_suggestion: ChangeFieldsToBeOfUnitType { num, spans: spans.clone() }, + parent_info, + ignored_derived_impls, + } + } else { + MultipleDeadCodes::DeadCodes { + multiple, + num, + descr, + participle, + name_list, + parent_info, + ignored_derived_impls, + } + }; - let encl_def_id = parent_item.unwrap_or(first_id); - if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) { - let traits_str = ign_traits - .iter() - .map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id))) - .collect::<Vec<_>>() - .join(" and "); - let plural_s = pluralize!(ign_traits.len()); - let article = if ign_traits.len() > 1 { "" } else { "a " }; - let is_are = if ign_traits.len() > 1 { "these are" } else { "this is" }; - let msg = format!( - "`{}` has {}derived impl{} for the trait{} {}, but {} \ - intentionally ignored during dead code analysis", - self.tcx.item_name(encl_def_id.to_def_id()), - article, - plural_s, - plural_s, - traits_str, - is_are - ); - err.note(&msg); - } - err - }, - ); - } + self.tcx.emit_spanned_lint( + lint, + tcx.hir().local_def_id_to_hir_id(first_id), + MultiSpan::from_spans(spans), + diag, + ); } fn warn_dead_fields_and_variants( diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index adaaf5392..c6cd69add 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -4,7 +4,9 @@ use std::{ }; use rustc_ast::Label; -use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; +use rustc_errors::{ + error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan, +}; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{MainDefinition, Ty}; @@ -79,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -95,6 +98,7 @@ pub struct TrackedCallerWrongLocation { pub attr_span: Span, #[label] pub defn_span: Span, + pub on_crate: bool, } #[derive(Diagnostic)] @@ -291,7 +295,7 @@ pub struct DocTestUnknownAny { #[note(no_op_note)] pub struct DocTestUnknownSpotlight { pub path: String, - #[suggestion_short(applicability = "machine-applicable", code = "notable_trait")] + #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")] pub span: Span, } @@ -365,6 +369,7 @@ pub struct MustNotSuspend { pub struct Cold { #[label] pub span: Span, + pub on_crate: bool, } #[derive(LintDiagnostic)] @@ -702,14 +707,6 @@ pub struct UnknownExternLangItem { pub struct MissingPanicHandler; #[derive(Diagnostic)] -#[diag(passes_alloc_func_required)] -pub struct AllocFuncRequired; - -#[derive(Diagnostic)] -#[diag(passes_missing_alloc_error_handler)] -pub struct MissingAllocErrorHandler; - -#[derive(Diagnostic)] #[diag(passes_missing_lang_item)] #[note] #[help] @@ -744,6 +741,7 @@ pub struct InvalidAttrAtCrateLevel { } impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { + #[track_caller] fn into_diagnostic( self, handler: &'_ rustc_errors::Handler, @@ -876,6 +874,7 @@ pub struct BreakNonLoop<'a> { } impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> { + #[track_caller] fn into_diagnostic( self, handler: &rustc_errors::Handler, @@ -960,6 +959,7 @@ pub struct OutsideLoop<'a> { #[label] pub span: Span, pub name: &'a str, + pub is_break: bool, } #[derive(Diagnostic)] @@ -1013,6 +1013,7 @@ pub struct NakedFunctionsAsmBlock { } impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock { + #[track_caller] fn into_diagnostic( self, handler: &rustc_errors::Handler, @@ -1136,6 +1137,7 @@ pub struct NoMainErr { } impl<'a> IntoDiagnostic<'a> for NoMainErr { + #[track_caller] fn into_diagnostic( self, handler: &'a rustc_errors::Handler, @@ -1196,6 +1198,7 @@ pub struct DuplicateLangItem { } impl IntoDiagnostic<'_> for DuplicateLangItem { + #[track_caller] fn into_diagnostic( self, handler: &rustc_errors::Handler, @@ -1449,3 +1452,59 @@ pub struct MissingConstErr { #[label] pub const_span: Span, } + +#[derive(LintDiagnostic)] +pub enum MultipleDeadCodes<'tcx> { + #[diag(passes_dead_codes)] + DeadCodes { + multiple: bool, + num: usize, + descr: &'tcx str, + participle: &'tcx str, + name_list: DiagnosticSymbolList, + #[subdiagnostic] + parent_info: Option<ParentInfo<'tcx>>, + #[subdiagnostic] + ignored_derived_impls: Option<IgnoredDerivedImpls>, + }, + #[diag(passes_dead_codes)] + UnusedTupleStructFields { + multiple: bool, + num: usize, + descr: &'tcx str, + participle: &'tcx str, + name_list: DiagnosticSymbolList, + #[subdiagnostic] + change_fields_suggestion: ChangeFieldsToBeOfUnitType, + #[subdiagnostic] + parent_info: Option<ParentInfo<'tcx>>, + #[subdiagnostic] + ignored_derived_impls: Option<IgnoredDerivedImpls>, + }, +} + +#[derive(Subdiagnostic)] +#[label(passes_parent_info)] +pub struct ParentInfo<'tcx> { + pub num: usize, + pub descr: &'tcx str, + pub parent_descr: &'tcx str, + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[note(passes_ignored_derived_impls)] +pub struct IgnoredDerivedImpls { + pub name: Symbol, + pub trait_list: DiagnosticSymbolList, + pub trait_list_len: usize, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_change_fields_to_be_of_unit_type, applicability = "has-placeholders")] +pub struct ChangeFieldsToBeOfUnitType { + pub num: usize, + #[suggestion_part(code = "()")] + pub spans: Vec<Span>, +} diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 88bb39deb..d143adb2e 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,11 +1,11 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit; use rustc_hir::{HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; -use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{DefIdTree, TyCtxt}; pub fn check_crate(tcx: TyCtxt<'_>) { tcx.dep_graph.assert_ignored(); @@ -17,11 +17,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { #[cfg(debug_assertions)] { let errors = Lock::new(Vec::new()); - let hir_map = tcx.hir(); - hir_map.par_for_each_module(|module_id| { + tcx.hir().par_for_each_module(|module_id| { let mut v = HirIdValidator { - hir_map, + tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors, @@ -40,20 +39,15 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } struct HirIdValidator<'a, 'hir> { - hir_map: Map<'hir>, + tcx: TyCtxt<'hir>, owner: Option<hir::OwnerId>, hir_ids_seen: GrowableBitSet<ItemLocalId>, errors: &'a Lock<Vec<String>>, } impl<'a, 'hir> HirIdValidator<'a, 'hir> { - fn new_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> { - HirIdValidator { - hir_map, - owner: None, - hir_ids_seen: Default::default(), - errors: self.errors, - } + fn new_visitor(&self, tcx: TyCtxt<'hir>) -> HirIdValidator<'a, 'hir> { + HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: self.errors } } #[cold] @@ -96,36 +90,69 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { missing_items.push(format!( "[local_id: {}, owner: {}]", local_id, - self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose() + self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose() )); } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}", - self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose(), + self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(), max, missing_items, self.hir_ids_seen .iter() .map(|local_id| HirId { owner, local_id }) - .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) + .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h))) .collect::<Vec<_>>() ) }); } } + + fn check_nested_id(&mut self, id: LocalDefId) { + let Some(owner) = self.owner else { return }; + let def_parent = self.tcx.local_parent(id); + let def_parent_hir_id = self.tcx.local_def_id_to_hir_id(def_parent); + if def_parent_hir_id.owner != owner { + self.error(|| { + format!( + "inconsistent Def parent at `{:?}` for `{:?}`:\nexpected={:?}\nfound={:?}", + self.tcx.def_span(id), + id, + owner, + def_parent_hir_id + ) + }); + } + } } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { - self.hir_map + self.tcx.hir() + } + + fn visit_nested_item(&mut self, id: hir::ItemId) { + self.check_nested_id(id.owner_id.def_id); + } + + fn visit_nested_trait_item(&mut self, id: hir::TraitItemId) { + self.check_nested_id(id.owner_id.def_id); + } + + fn visit_nested_impl_item(&mut self, id: hir::ImplItemId) { + self.check_nested_id(id.owner_id.def_id); + } + + fn visit_nested_foreign_item(&mut self, id: hir::ForeignItemId) { + self.check_nested_id(id.owner_id.def_id); } fn visit_item(&mut self, i: &'hir hir::Item<'hir>) { - let mut inner_visitor = self.new_visitor(self.hir_map); + let mut inner_visitor = self.new_visitor(self.tcx); inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i)); } @@ -136,9 +163,9 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { self.error(|| { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", - self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), - self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose() + self.tcx.hir().node_to_string(hir_id), + self.tcx.hir().def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), + self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose() ) }); } @@ -147,17 +174,17 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { } fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) { - let mut inner_visitor = self.new_visitor(self.hir_map); + let mut inner_visitor = self.new_visitor(self.tcx); inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i)); } fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) { - let mut inner_visitor = self.new_visitor(self.hir_map); + let mut inner_visitor = self.new_visitor(self.tcx); inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i)); } fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) { - let mut inner_visitor = self.new_visitor(self.hir_map); + let mut inner_visitor = self.new_visitor(self.tcx); inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i)); } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 33220fd2b..a7854cd49 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -369,7 +369,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, p: &'v hir::Path<'v>, hir_id: hir::HirId) { + fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: hir::HirId) { // This is `visit_use`, but the type is `Path` so record it that way. self.record("Path", Id::None, p); hir_visit::walk_use(self, p, hir_id) @@ -442,7 +442,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_lifetime(self, lifetime) } - fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'v>, _id: hir::HirId) { self.record("Path", Id::None, path); hir_visit::walk_path(self, path) } @@ -560,13 +560,14 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_expr(&mut self, e: &'v ast::Expr) { + #[rustfmt::skip] record_variants!( (self, e, e.kind, Id::None, ast, Expr, ExprKind), [ Box, 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, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, Err + InlineAsm, 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 df811be2a..99efed0b7 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -16,7 +16,7 @@ use crate::weak_lang_items; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS}; +use rustc_hir::lang_items::{extract, GenericRequirement}; use rustc_hir::{HirId, LangItem, LanguageItems, Target}; use rustc_middle::ty::TyCtxt; use rustc_session::cstore::ExternCrate; @@ -43,17 +43,17 @@ impl<'tcx> LanguageItemCollector<'tcx> { fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) { let attrs = self.tcx.hir().attrs(hir_id); if let Some((name, span)) = extract(&attrs) { - match ITEM_REFS.get(&name).cloned() { + match LangItem::from_name(name) { // Known lang item with attribute on correct target. - Some((item_index, expected_target)) if actual_target == expected_target => { - self.collect_item_extended(item_index, hir_id, span); + Some(lang_item) if actual_target == lang_item.target() => { + self.collect_item_extended(lang_item, hir_id, span); } // Known lang item with attribute on incorrect target. - Some((_, expected_target)) => { + Some(lang_item) => { self.tcx.sess.emit_err(LangItemOnIncorrectTarget { span, name, - expected_target, + expected_target: lang_item.target(), actual_target, }); } @@ -65,12 +65,12 @@ impl<'tcx> LanguageItemCollector<'tcx> { } } - fn collect_item(&mut self, item_index: usize, item_def_id: DefId) { + fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) { // Check for duplicates. - if let Some(original_def_id) = self.items.items[item_index] { + if let Some(original_def_id) = self.items.get(lang_item) { if original_def_id != item_def_id { let local_span = self.tcx.hir().span_if_local(item_def_id); - let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name(); + let lang_item_name = lang_item.name(); let crate_name = self.tcx.crate_name(item_def_id.krate); let mut dependency_of = Empty; let is_local = item_def_id.is_local(); @@ -139,17 +139,13 @@ impl<'tcx> LanguageItemCollector<'tcx> { } // Matched. - self.items.items[item_index] = Some(item_def_id); - if let Some(group) = LangItem::from_u32(item_index as u32).unwrap().group() { - self.items.groups[group as usize].push(item_def_id); - } + self.items.set(lang_item, item_def_id); } // Like collect_item() above, but also checks whether the lang item is declared // with the right number of generic arguments. - fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) { + fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) { let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id(); - let lang_item = LangItem::from_u32(item_index as u32).unwrap(); let name = lang_item.name(); // Now check whether the lang_item has the expected number of generic @@ -197,7 +193,7 @@ impl<'tcx> LanguageItemCollector<'tcx> { } } - self.collect_item(item_index, item_def_id); + self.collect_item(lang_item, item_def_id); } } @@ -208,8 +204,8 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { // Collect lang items in other crates. for &cnum in tcx.crates(()).iter() { - for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { - collector.collect_item(item_index, def_id); + for &(def_id, lang_item) in tcx.defined_lang_items(cnum).iter() { + collector.collect_item(lang_item, def_id); } } @@ -223,7 +219,7 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(def, ..) = &item.kind { for variant in def.variants { - collector.check_for_lang(Target::Variant, variant.id); + collector.check_for_lang(Target::Variant, variant.hir_id); } } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 15f60f626..6e621b7eb 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -5,8 +5,6 @@ //! This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index c6fe40f72..1f65cc8b6 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -87,6 +87,7 @@ 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}; @@ -412,7 +413,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } intravisit::walk_expr(self, expr); } - hir::ExprKind::Closure { .. } => { + hir::ExprKind::Closure(closure) => { // Interesting control flow (for loops can contain labeled // breaks or continues) self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id)); @@ -422,8 +423,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { // in better error messages than just pointing at the closure // construction site. let mut call_caps = Vec::new(); - let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id); - if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { + if let Some(upvars) = self.tcx.upvars_mentioned(closure.def_id) { call_caps.extend(upvars.keys().map(|var_id| { let upvar = upvars[var_id]; let upvar_ln = self.add_live_node(UpvarNode(upvar.span)); @@ -922,8 +922,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // v v // ( succ ) // - let else_ln = - self.propagate_through_opt_expr(else_opt.as_ref().map(|e| &**e), succ); + let else_ln = self.propagate_through_opt_expr(else_opt.as_deref(), succ); let then_ln = self.propagate_through_expr(&then, succ); let ln = self.live_node(expr.hir_id, expr.span); self.init_from_succ(ln, else_ln); @@ -966,7 +965,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Ret(ref o_e) => { // Ignore succ and subst exit_ln. - self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), self.exit_ln) + self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln) } hir::ExprKind::Break(label, ref opt_expr) => { @@ -981,7 +980,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // look it up in the break loop nodes table match target { - Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b), + Some(b) => self.propagate_through_opt_expr(opt_expr.as_deref(), b), None => span_bug!(expr.span, "`break` to unknown label"), } } @@ -1026,7 +1025,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Array(ref exprs) => self.propagate_through_exprs(exprs, succ), hir::ExprKind::Struct(_, ref fields, ref with_expr) => { - let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ); + let succ = self.propagate_through_opt_expr(with_expr.as_deref(), succ); fields .iter() .rev() @@ -1284,20 +1283,19 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { let ty = self.typeck_results.expr_ty(expr); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); - if self.ir.tcx.is_ty_uninhabited_from(m, ty, self.param_env) { - match self.ir.lnks[succ] { - LiveNodeKind::ExprNode(succ_span, succ_id) => { - self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression"); - } - LiveNodeKind::VarDefNode(succ_span, succ_id) => { - self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition"); - } - _ => {} - }; - self.exit_ln - } else { - succ + if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) { + return succ; } + match self.ir.lnks[succ] { + LiveNodeKind::ExprNode(succ_span, succ_id) => { + self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression"); + } + LiveNodeKind::VarDefNode(succ_span, succ_id) => { + self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition"); + } + _ => {} + }; + self.exit_ln } fn warn_about_unreachable( @@ -1550,7 +1548,13 @@ impl<'tcx> Liveness<'_, 'tcx> { .or_insert_with(|| (ln, var, vec![id_and_sp])); }); - let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true)); + let can_remove = match pat.kind { + hir::PatKind::Struct(_, fields, true) => { + // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix + fields.iter().all(|f| f.is_shorthand) + } + _ => false, + }; for (_, (ln, var, hir_ids_and_spans)) in vars { if self.used_on_entry(ln, var) { @@ -1690,7 +1694,7 @@ impl<'tcx> Liveness<'_, 'tcx> { &self, name: &str, opt_body: Option<&hir::Body<'_>>, - err: &mut rustc_errors::DiagnosticBuilder<'_, ()>, + err: &mut Diagnostic, ) -> bool { let mut has_litstring = false; let Some(opt_body) = opt_body else {return false;}; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 077194ec6..b4cf19e4a 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -193,7 +193,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } Normal | AnonConst => { - self.sess.emit_err(OutsideLoop { span, name }); + self.sess.emit_err(OutsideLoop { span, name, is_break: name == "break" }); } } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 50070869a..e7c3c7128 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -391,11 +391,9 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { }) .collect::<Vec<_>>(); - for item in tcx.lang_items().items().iter() { - if let Some(def_id) = *item { - if let Some(def_id) = def_id.as_local() { - reachable_context.worklist.push(def_id); - } + for (_, def_id) in tcx.lang_items().iter() { + if let Some(def_id) = def_id.as_local() { + reachable_context.worklist.push(def_id); } } { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 78afa2f25..da7155234 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -358,9 +358,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { const_stab_inherit = InheritConstStability::Yes; } hir::ItemKind::Struct(ref sd, _) => { - if let Some(ctor_hir_id) = sd.ctor_hir_id() { + if let Some(ctor_def_id) = sd.ctor_def_id() { self.annotate( - self.tcx.hir().local_def_id(ctor_hir_id), + ctor_def_id, i.span, None, AnnotationKind::Required, @@ -435,7 +435,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) { self.annotate( - self.tcx.hir().local_def_id(var.id), + var.def_id, var.span, None, AnnotationKind::Required, @@ -443,9 +443,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { InheritConstStability::No, InheritStability::Yes, |v| { - if let Some(ctor_hir_id) = var.data.ctor_hir_id() { + if let Some(ctor_def_id) = var.data.ctor_def_id() { v.annotate( - v.tcx.hir().local_def_id(ctor_hir_id), + ctor_def_id, var.span, None, AnnotationKind::Required, @@ -463,7 +463,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) { self.annotate( - self.tcx.hir().local_def_id(s.hir_id), + s.def_id, s.span, None, AnnotationKind::Required, @@ -500,7 +500,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - self.tcx.hir().local_def_id(p.hir_id), + p.def_id, p.span, None, kind, @@ -536,6 +536,14 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { return; } + // if the const impl is derived using the `derive_const` attribute, + // then it would be "stable" at least for the impl. + // We gate usages of it using `feature(const_trait_impl)` anyways + // so there is no unstable leakage + if self.tcx.is_builtin_derive(def_id.to_def_id()) { + return; + } + 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 @@ -593,15 +601,15 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) { - self.check_missing_stability(self.tcx.hir().local_def_id(var.id), var.span); - if let Some(ctor_hir_id) = var.data.ctor_hir_id() { - self.check_missing_stability(self.tcx.hir().local_def_id(ctor_hir_id), var.span); + self.check_missing_stability(var.def_id, var.span); + if let Some(ctor_def_id) = var.data.ctor_def_id() { + self.check_missing_stability(ctor_def_id, var.span); } intravisit::walk_variant(self, var); } fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) { - self.check_missing_stability(self.tcx.hir().local_def_id(s.hir_id), s.span); + self.check_missing_stability(s.def_id, s.span); intravisit::walk_field_def(self, s); } @@ -779,7 +787,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { intravisit::walk_item(self, item); } - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { let method_span = path.segments.last().map(|s| s.ident.span); let item_is_allowed = self.tcx.check_stability_allow_unstable( @@ -872,7 +880,7 @@ struct CheckTraitImplStable<'tcx> { } impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _id: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: hir::HirId) { if let Some(def_id) = path.res.opt_def_id() { if let Some(stab) = self.tcx.lookup_stability(def_id) { self.fully_stable &= stab.level.is_stable(); diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 68d9bf22b..605cf0a93 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -66,7 +66,7 @@ impl CaptureCollector<'_, '_> { } impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> { - fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { if let Res::Local(var_id) = path.res { self.visit_local_use(var_id, path.span); } @@ -75,9 +75,8 @@ impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Closure { .. } = expr.kind { - let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id); - if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { + if let hir::ExprKind::Closure(closure) = expr.kind { + if let Some(upvars) = self.tcx.upvars_mentioned(closure.def_id) { // Every capture of a closure expression is a local in scope, // that is moved/copied/borrowed into the closure value, and // for this analysis they are like any other access to a local. diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 959ee600c..f0815fcd8 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -2,15 +2,12 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::lang_items::{self, LangItem}; -use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS; +use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use crate::errors::{ - AllocFuncRequired, MissingAllocErrorHandler, MissingLangItem, MissingPanicHandler, - UnknownExternLangItem, -}; +use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}; /// Checks the crate for usage of weak lang items, returning a vector of all the /// language items required by this crate, but not defined yet. @@ -29,8 +26,8 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem for id in crate_items.foreign_items() { let attrs = tcx.hir().attrs(id.hir_id()); if let Some((lang_item, _)) = lang_items::extract(attrs) { - if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) { - if items.require(item).is_err() { + if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() { + if items.get(item).is_none() { items.missing.push(item); } } else { @@ -65,17 +62,12 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { } } - for (name, &item) in WEAK_ITEMS_REFS.iter() { - if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() { + for &item in WEAK_LANG_ITEMS.iter() { + if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() { if item == LangItem::PanicImpl { tcx.sess.emit_err(MissingPanicHandler); - } else if item == LangItem::Oom { - if !tcx.features().default_alloc_error_handler { - tcx.sess.emit_err(AllocFuncRequired); - tcx.sess.emit_note(MissingAllocErrorHandler); - } } else { - tcx.sess.emit_err(MissingLangItem { name: *name }); + tcx.sess.emit_err(MissingLangItem { name: item.name() }); } } } |