diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 258 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/input_stats.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/lib_features.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/reachable.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 26 |
7 files changed, 165 insertions, 165 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c68f8df49fc..5b7d45bb152 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,7 +10,7 @@ use std::collections::hash_map::Entry; use rustc_abi::{Align, ExternAbi, Size}; use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast}; -use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr}; +use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; -use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; @@ -255,7 +255,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - [sym::autodiff, ..] => { + [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } [sym::coroutine, ..] => { @@ -802,7 +802,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Struct => { if let Some(ItemLike::Item(hir::Item { - kind: hir::ItemKind::Struct(_, hir::VariantData::Struct { fields, .. }, _), + kind: hir::ItemKind::Struct(_, _, hir::VariantData::Struct { fields, .. }), .. })) = item && !fields.is_empty() @@ -936,7 +936,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let span = meta.name_value_literal_span().unwrap_or_else(|| meta.span()); let attr_str = &format!("`#[doc(alias{})]`", if is_list { "(\"...\")" } else { " = \"...\"" }); - if doc_alias == kw::Empty { + if doc_alias == sym::empty { tcx.dcx().emit_err(errors::DocAliasEmpty { span, attr_str }); return; } @@ -1068,7 +1068,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } let doc_keyword = match meta.value_str() { - Some(value) if value != kw::Empty => value, + Some(value) if value != sym::empty => value, _ => return self.doc_attr_str_error(meta, "keyword"), }; @@ -1130,12 +1130,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; }; match item.kind { - ItemKind::Enum(_, _, generics) | ItemKind::Struct(_, _, generics) + ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) if generics.params.len() != 0 => {} ItemKind::Trait(_, _, _, generics, _, items) if generics.params.len() != 0 || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {} - ItemKind::TyAlias(_, _, generics) if generics.params.len() != 0 => {} + ItemKind::TyAlias(_, generics, _) if generics.params.len() != 0 => {} _ => { self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() }); } @@ -2312,7 +2312,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) { - let name = attr.name().unwrap(); + let Some(name) = attr.name() else { + return; + }; match target { Target::ExternCrate | Target::Mod => {} _ => { @@ -2792,7 +2794,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn is_c_like_enum(item: &Item<'_>) -> bool { - if let ItemKind::Enum(_, ref def, _) = item.kind { + if let ItemKind::Enum(_, _, ref def) = item.kind { for variant in def.variants { match variant.data { hir::VariantData::Unit(..) => { /* continue */ } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 0060e726a8e..6b82252f32c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -8,12 +8,13 @@ use std::mem; use hir::ItemKind; use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Node, PatKind, TyKind}; +use rustc_hir::{self as hir, Node, PatKind, QPath, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -44,15 +45,20 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { ) } -fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool { - if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind - && let Res::Def(def_kind, def_id) = path.res - && def_id.is_local() - && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) - { - tcx.visibility(def_id).is_public() - } else { - true +/// Returns the local def id of the ADT if the given ty refers to a local one. +fn local_adt_def_of_ty<'tcx>(ty: &hir::Ty<'tcx>) -> Option<LocalDefId> { + match ty.kind { + TyKind::Path(QPath::Resolved(_, path)) => { + if let Res::Def(def_kind, def_id) = path.res + && let Some(local_def_id) = def_id.as_local() + && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) + { + Some(local_def_id) + } else { + None + } + } + _ => None, } } @@ -78,7 +84,7 @@ struct MarkSymbolVisitor<'tcx> { // maps from ADTs to ignored derived traits (e.g. Debug and Clone) // and the span of their respective impl (i.e., part of the derive // macro) - ignored_derived_traits: LocalDefIdMap<Vec<(DefId, DefId)>>, + ignored_derived_traits: LocalDefIdMap<FxIndexSet<(DefId, DefId)>>, } impl<'tcx> MarkSymbolVisitor<'tcx> { @@ -360,7 +366,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let Some(fn_sig) = self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) - && let TyKind::Path(hir::QPath::Resolved(_, path)) = + && let TyKind::Path(QPath::Resolved(_, path)) = self.tcx.hir_expect_item(local_impl_of).expect_impl().self_ty.kind && let Res::Def(def_kind, did) = path.res { @@ -388,7 +394,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { self.ignored_derived_traits .entry(adt_def_id) .or_default() - .push((trait_of, impl_of)); + .insert((trait_of, impl_of)); } return true; } @@ -420,51 +426,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} - hir::ItemKind::Trait(..) => { - for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) { - if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind - { - // skip items - // mark dependent traits live - intravisit::walk_generics(self, impl_ref.generics); - // mark dependent parameters live - intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); + hir::ItemKind::Trait(.., trait_item_refs) => { + // mark assoc ty live if the trait is live + for trait_item in trait_item_refs { + if matches!(trait_item.kind, hir::AssocItemKind::Type) { + self.check_def_id(trait_item.id.owner_id.to_def_id()); } } - intravisit::walk_item(self, item) } _ => intravisit::walk_item(self, item), }, Node::TraitItem(trait_item) => { - // mark corresponding ImplTerm live + // mark the trait live let trait_item_id = trait_item.owner_id.to_def_id(); if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) { - // mark the trait live self.check_def_id(trait_id); - - for impl_id in self.tcx.all_impls(trait_id) { - if let Some(local_impl_id) = impl_id.as_local() - && let ItemKind::Impl(impl_ref) = - self.tcx.hir_expect_item(local_impl_id).kind - { - if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) - && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - { - // skip methods of private ty, - // they would be solved in `solve_rest_impl_items` - continue; - } - - // mark self_ty live - intravisit::walk_unambig_ty(self, impl_ref.self_ty); - if let Some(&impl_item_id) = - self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) - { - self.check_def_id(impl_item_id); - } - } - } } intravisit::walk_trait_item(self, trait_item); } @@ -508,48 +485,58 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - fn solve_rest_impl_items(&mut self, mut unsolved_impl_items: Vec<(hir::ItemId, LocalDefId)>) { - let mut ready; - (ready, unsolved_impl_items) = - unsolved_impl_items.into_iter().partition(|&(impl_id, impl_item_id)| { - self.impl_item_with_used_self(impl_id, impl_item_id) - }); - - while !ready.is_empty() { - self.worklist = - ready.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect(); - self.mark_live_symbols(); - - (ready, unsolved_impl_items) = - unsolved_impl_items.into_iter().partition(|&(impl_id, impl_item_id)| { - self.impl_item_with_used_self(impl_id, impl_item_id) - }); + /// Returns whether `local_def_id` is potentially alive or not. + /// `local_def_id` points to an impl or an impl item, + /// both impl and impl item that may be passed to this function are of a trait, + /// and added into the unsolved_items during `create_and_seed_worklist` + fn check_impl_or_impl_item_live( + &mut self, + impl_id: hir::ItemId, + local_def_id: LocalDefId, + ) -> bool { + if self.should_ignore_item(local_def_id.to_def_id()) { + return false; } - } - fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool { - if let TyKind::Path(hir::QPath::Resolved(_, path)) = - self.tcx.hir_item(impl_id).expect_impl().self_ty.kind - && let Res::Def(def_kind, def_id) = path.res - && let Some(local_def_id) = def_id.as_local() - && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) - { - if self.tcx.visibility(impl_item_id).is_public() { - // for the public method, we don't know the trait item is used or not, - // so we mark the method live if the self is used - return self.live_symbols.contains(&local_def_id); + let trait_def_id = match self.tcx.def_kind(local_def_id) { + // assoc impl items of traits are live if the corresponding trait items are live + DefKind::AssocFn => self.tcx.associated_item(local_def_id).trait_item_def_id, + // impl items are live if the corresponding traits are live + DefKind::Impl { of_trait: true } => self + .tcx + .impl_trait_ref(impl_id.owner_id.def_id) + .and_then(|trait_ref| Some(trait_ref.skip_binder().def_id)), + _ => None, + }; + + if let Some(trait_def_id) = trait_def_id { + if let Some(trait_def_id) = trait_def_id.as_local() + && !self.live_symbols.contains(&trait_def_id) + { + return false; } - if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id - && let Some(local_id) = trait_item_id.as_local() + // FIXME: legacy logic to check whether the function may construct `Self`, + // this can be removed after supporting marking ADTs appearing in patterns + // as live, then we can check private impls of public traits directly + if let Some(fn_sig) = + self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) + && self.tcx.visibility(trait_def_id).is_public() { - // for the private method, we can know the trait item is used or not, - // so we mark the method live if the self is used and the trait item is used - return self.live_symbols.contains(&local_id) - && self.live_symbols.contains(&local_def_id); + return true; } } - false + + // The impl or impl item is used if the corresponding trait or trait item is used and the ty is used. + if let Some(local_def_id) = + local_adt_def_of_ty(self.tcx.hir_item(impl_id).expect_impl().self_ty) + && !self.live_symbols.contains(&local_def_id) + { + return false; + } + + true } } @@ -584,7 +571,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { match expr.kind { - hir::ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { + hir::ExprKind::Path(ref qpath @ QPath::TypeRelative(..)) => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); self.handle_res(res); } @@ -707,7 +694,7 @@ fn has_allow_dead_code_or_lang_attr( // #[used], #[no_mangle], #[export_name], etc also keeps the item alive // forcefully, e.g., for placing it in a specific section. cg_attrs.contains_extern_indicator() - || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) + || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) } } @@ -738,7 +725,7 @@ fn check_item<'tcx>( tcx: TyCtxt<'tcx>, worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, struct_constructors: &mut LocalDefIdMap<LocalDefId>, - unsolved_impl_items: &mut Vec<(hir::ItemId, LocalDefId)>, + unsolved_items: &mut Vec<(hir::ItemId, LocalDefId)>, id: hir::ItemId, ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id); @@ -749,7 +736,7 @@ fn check_item<'tcx>( match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir_item(id); - if let hir::ItemKind::Enum(_, ref enum_def, _) = item.kind { + if let hir::ItemKind::Enum(_, _, ref enum_def) = item.kind { if let Some(comes_from_allow) = allow_dead_code { worklist.extend( enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)), @@ -764,47 +751,39 @@ fn check_item<'tcx>( } } DefKind::Impl { of_trait } => { - // get DefIds from another query - let local_def_ids = tcx - .associated_item_def_ids(id.owner_id) - .iter() - .filter_map(|def_id| def_id.as_local()); - - let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir_item(id).expect_impl().self_ty); - - // And we access the Map here to get HirId from LocalDefId - for local_def_id in local_def_ids { - // check the function may construct Self - let mut may_construct_self = false; - if let Some(fn_sig) = - tcx.hir_fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id)) - { - may_construct_self = - matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None); - } + if let Some(comes_from_allow) = + has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id) + { + worklist.push((id.owner_id.def_id, comes_from_allow)); + } else if of_trait { + unsolved_items.push((id, id.owner_id.def_id)); + } - // for trait impl blocks, - // mark the method live if the self_ty is public, - // or the method is public and may construct self - if of_trait - && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) - || tcx.visibility(local_def_id).is_public() - && (ty_is_pub || may_construct_self)) - { - worklist.push((local_def_id, ComesFromAllowExpect::No)); - } else if let Some(comes_from_allow) = - has_allow_dead_code_or_lang_attr(tcx, local_def_id) + for def_id in tcx.associated_item_def_ids(id.owner_id) { + let local_def_id = def_id.expect_local(); + + if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, local_def_id) { worklist.push((local_def_id, comes_from_allow)); } else if of_trait { - // private method || public method not constructs self - unsolved_impl_items.push((id, local_def_id)); + // FIXME: This condition can be removed + // if we support dead check for assoc consts and tys. + if !matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) { + worklist.push((local_def_id, ComesFromAllowExpect::No)); + } else { + // We only care about associated items of traits, + // because they cannot be visited directly, + // so we later mark them as live if their corresponding traits + // or trait items and self types are both live, + // but inherent associated items can be visited and marked directly. + unsolved_items.push((id, local_def_id)); + } } } } DefKind::Struct => { let item = tcx.hir_item(id); - if let hir::ItemKind::Struct(_, ref variant_data, _) = item.kind + if let hir::ItemKind::Struct(_, _, ref variant_data) = item.kind && let Some(ctor_def_id) = variant_data.ctor_def_id() { struct_constructors.insert(ctor_def_id, item.owner_id.def_id); @@ -892,8 +871,8 @@ fn create_and_seed_worklist( fn live_symbols_and_ignored_derived_traits( tcx: TyCtxt<'_>, (): (), -) -> (LocalDefIdSet, LocalDefIdMap<Vec<(DefId, DefId)>>) { - let (worklist, struct_constructors, unsolved_impl_items) = create_and_seed_worklist(tcx); +) -> (LocalDefIdSet, LocalDefIdMap<FxIndexSet<(DefId, DefId)>>) { + let (worklist, struct_constructors, mut unsolved_items) = create_and_seed_worklist(tcx); let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, @@ -907,7 +886,22 @@ fn live_symbols_and_ignored_derived_traits( ignored_derived_traits: Default::default(), }; symbol_visitor.mark_live_symbols(); - symbol_visitor.solve_rest_impl_items(unsolved_impl_items); + let mut items_to_check; + (items_to_check, unsolved_items) = + unsolved_items.into_iter().partition(|&(impl_id, local_def_id)| { + symbol_visitor.check_impl_or_impl_item_live(impl_id, local_def_id) + }); + + while !items_to_check.is_empty() { + symbol_visitor.worklist = + items_to_check.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect(); + symbol_visitor.mark_live_symbols(); + + (items_to_check, unsolved_items) = + unsolved_items.into_iter().partition(|&(impl_id, local_def_id)| { + symbol_visitor.check_impl_or_impl_item_live(impl_id, local_def_id) + }); + } (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits) } @@ -921,7 +915,7 @@ struct DeadItem { struct DeadVisitor<'tcx> { tcx: TyCtxt<'tcx>, live_symbols: &'tcx LocalDefIdSet, - ignored_derived_traits: &'tcx LocalDefIdMap<Vec<(DefId, DefId)>>, + ignored_derived_traits: &'tcx LocalDefIdMap<FxIndexSet<(DefId, DefId)>>, } enum ShouldWarnAboutField { @@ -1061,7 +1055,7 @@ impl<'tcx> DeadVisitor<'tcx> { let tuple_fields = if let Some(parent_id) = parent_item && let node = tcx.hir_node_by_def_id(parent_id) && let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(fields, _, _), _), + kind: hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(fields, _, _)), .. }) = node { @@ -1188,19 +1182,15 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let def_kind = tcx.def_kind(item.owner_id); let mut dead_codes = Vec::new(); - // if we have diagnosed the trait, do not diagnose unused methods - if matches!(def_kind, DefKind::Impl { .. }) + // Only diagnose unused assoc items in inherient impl and used trait, + // for unused assoc items in impls of trait, + // we have diagnosed them in the trait if they are unused, + // for unused assoc items in unused trait, + // we have diagnosed the unused trait. + if matches!(def_kind, DefKind::Impl { of_trait: false }) || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused methods in traits - if matches!(def_kind, DefKind::Impl { of_trait: true }) - && tcx.def_kind(def_id) == DefKind::AssocFn - || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn - { - continue; - } - if let Some(local_def_id) = def_id.as_local() && !visitor.is_live_code(local_def_id) { diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 71815448172..6852153a2e7 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -426,10 +426,16 @@ 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::UsePath<'v>, hir_id: HirId) { + fn visit_use(&mut self, p: &'v hir::UsePath<'v>, _hir_id: HirId) { // This is `visit_use`, but the type is `Path` so record it that way. self.record("Path", None, p); - hir_visit::walk_use(self, p, hir_id) + // Don't call `hir_visit::walk_use(self, p, hir_id)`: it calls + // `visit_path` up to three times, once for each namespace result in + // `p.res`, by building temporary `Path`s that are not part of the real + // HIR, which causes `p` to be double- or triple-counted. Instead just + // walk the path internals (i.e. the segments) directly. + let hir::Path { span: _, res: _, segments } = *p; + ast_visit::walk_list!(self, visit_path_segment, segments); } fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) { diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 7353c1ead5a..b3e6ee9512c 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -4,7 +4,7 @@ //! but are not declared in one single location (unlike lang features), which means we need to //! collect them instead. -use rustc_attr_parsing::{AttributeKind, StabilityLevel, StableSince}; +use rustc_attr_data_structures::{AttributeKind, StabilityLevel, StableSince}; use rustc_hir::Attribute; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 4e9b7fd44d4..763d9fda804 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -122,7 +122,6 @@ enum LiveNodeKind { VarDefNode(Span, HirId), ClosureNode, ExitNode, - ErrNode, } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { @@ -133,7 +132,6 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)), ClosureNode => "Closure node".to_owned(), ExitNode => "Exit node".to_owned(), - ErrNode => "Error node".to_owned(), } } @@ -492,6 +490,9 @@ struct Liveness<'a, 'tcx> { impl<'a, 'tcx> Liveness<'a, 'tcx> { fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> { let typeck_results = ir.tcx.typeck(body_owner); + // Liveness linting runs after building the THIR. We make several assumptions based on + // typeck succeeding, e.g. that breaks and continues are well-formed. + assert!(typeck_results.tainted_by_errors.is_none()); // FIXME(#132279): we're in a body here. let typing_env = ty::TypingEnv::non_body_analysis(ir.tcx, body_owner); let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner); @@ -976,8 +977,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Now that we know the label we're going to, // look it up in the continue loop nodes table self.cont_ln.get(&sc).cloned().unwrap_or_else(|| { - self.ir.tcx.dcx().span_delayed_bug(expr.span, "continue to unknown label"); - self.ir.add_live_node(ErrNode) + // Liveness linting happens after building the THIR. Bad labels should already + // have been caught. + span_bug!(expr.span, "continue to unknown label"); }) } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f0e8fa986fe..7e15267a953 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -427,7 +427,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs. - || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED) + || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index d7baad69c78..45e26c8999a 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -5,9 +5,9 @@ use std::mem::replace; use std::num::NonZero; use rustc_ast_lowering::stability::extern_abi_stability; -use rustc_attr_parsing::{ - self as attr, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability, Stability, - StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr, +use rustc_attr_data_structures::{ + self as attrs, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability, + Stability, StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr, }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; @@ -121,7 +121,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs); - let depr = attr::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span)); + let depr = attrs::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span)); let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect); let mut is_deprecated = false; @@ -174,9 +174,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } // # Regular and body stability - let stab = attr::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span)); + let stab = attrs::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span)); let body_stab = - attr::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability); + attrs::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability); if let Some((depr, span)) = &depr && depr.is_since_rustc_version() @@ -206,7 +206,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // this is *almost surely* an accident. if let ( &Some(DeprecatedSince::RustcVersion(dep_since)), - &attr::StabilityLevel::Stable { since: stab_since, .. }, + &attrs::StabilityLevel::Stable { since: stab_since, .. }, ) = (&depr.as_ref().map(|(d, _)| d.since), &stab.level) { match stab_since { @@ -263,7 +263,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // # Const stability - let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span)); + let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span)); // If the current node is a function with const stability attributes (directly given or // implied), check if the function/method is const or the parent impl block is const. @@ -430,7 +430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { kind = AnnotationKind::DeprecationProhibited; const_stab_inherit = InheritConstStability::Yes; } - hir::ItemKind::Struct(_, ref sd, _) => { + hir::ItemKind::Struct(_, _, ref sd) => { if let Some(ctor_def_id) = sd.ctor_def_id() { self.annotate( ctor_def_id, @@ -713,7 +713,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { // by default and are unable to be used. if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { let stability = Stability { - level: attr::StabilityLevel::Unstable { + level: attrs::StabilityLevel::Unstable { reason: UnstableReason::Default, issue: NonZero::new(27812), is_soft: false, @@ -796,17 +796,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { let features = self.tcx.features(); if features.staged_api() { let attrs = self.tcx.hir_attrs(item.hir_id()); - let stab = attr::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span)); + let stab = attrs::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span)); // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability); + let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability); // If this impl block has an #[unstable] attribute, give an // error if all involved types and traits are stable, because // it will have no effect. // See: https://github.com/rust-lang/rust/issues/55436 if let Some(( - Stability { level: attr::StabilityLevel::Unstable { .. }, .. }, + Stability { level: attrs::StabilityLevel::Unstable { .. }, .. }, span, )) = stab { |
