summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:32 +0000
commit4547b622d8d29df964fa2914213088b148c498fc (patch)
tree9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_passes/src
parentReleasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz
rustc-4547b622d8d29df964fa2914213088b148c498fc.zip
Merging upstream version 1.67.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.rs96
-rw-r--r--compiler/rustc_passes/src/dead.rs200
-rw-r--r--compiler/rustc_passes/src/errors.rs79
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs75
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs7
-rw-r--r--compiler/rustc_passes/src/lang_items.rs34
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs50
-rw-r--r--compiler/rustc_passes/src/loops.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs8
-rw-r--r--compiler/rustc_passes/src/stability.rs34
-rw-r--r--compiler/rustc_passes/src/upvars.rs7
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs22
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() });
}
}
}