diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/abi_test.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 226 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_export.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/dead.rs | 74 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/input_stats.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/liveness.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/reachable.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 41 |
9 files changed, 280 insertions, 112 deletions
diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index b139ed6a66c..0ac42f03eb2 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -79,7 +79,7 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut for meta_item in meta_items { match meta_item.name() { Some(sym::debug) => { - let fn_name = tcx.item_name(item_def_id.into()); + let fn_name = tcx.item_name(item_def_id); tcx.dcx().emit_err(AbiOf { span: tcx.def_span(item_def_id), fn_name, @@ -135,7 +135,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut item_def_id, ); - let fn_name = tcx.item_name(item_def_id.into()); + let fn_name = tcx.item_name(item_def_id); tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); } Some(sym::assert_eq) => { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9e4e78c1db6..d8ffcedeb88 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -7,10 +7,12 @@ use std::cell::Cell; use std::collections::hash_map::Entry; +use std::slice; use rustc_abi::{Align, ExternAbi, Size}; -use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast}; +use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms}; use rustc_attr_data_structures::{AttributeKind, InlineAttr, ReprAttr, find_attr}; +use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; @@ -18,8 +20,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, self, AssocItemKind, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, - HirId, Item, ItemKind, MethodKind, Safety, Target, TraitItem, + self as hir, self, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId, Item, + ItemKind, MethodKind, Safety, Target, TraitItem, }; use rustc_macros::LintDiagnostic; use rustc_middle::hir::nested_filter; @@ -33,7 +35,7 @@ use rustc_session::config::CrateType; use rustc_session::lint; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, - UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, + MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; use rustc_span::edition::Edition; @@ -43,6 +45,7 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; +use crate::errors::AlignOnFields; use crate::{errors, fluent_generated as fluent}; #[derive(LintDiagnostic)] @@ -120,15 +123,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { let mut style = None; match attr { - Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch { - span: attr_span, - .. - }) => { + Attribute::Parsed( + AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. } + | AttributeKind::Coinductive(attr_span) + | AttributeKind::ConstTrait(attr_span) + | AttributeKind::DenyExplicitImpl(attr_span) + | AttributeKind::DoNotImplementViaObject(attr_span), + ) => { self.check_must_be_applied_to_trait(*attr_span, span, target); } + &Attribute::Parsed( + AttributeKind::SpecializationTrait(attr_span) + | AttributeKind::UnsafeSpecializationMarker(attr_span) + | AttributeKind::ParenSugar(attr_span), + ) => { + // FIXME: more validation is needed + self.check_must_be_applied_to_trait(attr_span, span, target); + } + &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => { + self.check_type_const(hir_id, attr_span, target) + } + &Attribute::Parsed(AttributeKind::Marker(attr_span)) => { + self.check_marker(hir_id, attr_span, span, target) + } + Attribute::Parsed(AttributeKind::Fundamental | AttributeKind::CoherenceIsCore) => { + // FIXME: add validation + } + &Attribute::Parsed(AttributeKind::AllowIncoherentImpl(attr_span)) => { + self.check_allow_incoherent_impl(attr_span, span, target) + } Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => { self.check_confusables(*first_span, target); } + Attribute::Parsed(AttributeKind::AutomaticallyDerived(attr_span)) => self + .check_generic_attr( + hir_id, + sym::automatically_derived, + *attr_span, + target, + Target::Impl, + ), Attribute::Parsed( AttributeKind::Stability { span, .. } | AttributeKind::ConstStability { span, .. }, @@ -174,8 +208,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { self.check_export_name(hir_id, *attr_span, span, target) } - Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { - self.check_align(span, target, *align, *repr_span) + Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => { + self.check_align(span, hir_id, target, *align, *attr_span) } Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => { self.check_link_section(hir_id, *attr_span, span, target) @@ -204,10 +238,25 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span) | AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span), ) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target), + Attribute::Parsed(AttributeKind::ExportStable) => { + // handled in `check_export` + } + &Attribute::Parsed(AttributeKind::FfiConst(attr_span)) => { + self.check_ffi_const(attr_span, target) + } + &Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => { + self.check_ffi_pure(attr_span, attrs, target) + } + Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => { + self.check_unstable_feature_bound(syms.first().unwrap().1, span, target) + } Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect - | AttributeKind::MacroTransparency(_), + | AttributeKind::MacroTransparency(_) + | AttributeKind::Pointee(..) + | AttributeKind::Dummy + | AttributeKind::OmitGdbPrettyPrinterSection, ) => { /* do nothing */ } Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) @@ -215,6 +264,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => { self.check_link_name(hir_id, *attr_span, *name, span, target) } + Attribute::Parsed(AttributeKind::LinkOrdinal { span: attr_span, .. }) => { + self.check_link_ordinal(*attr_span, span, target) + } Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { self.check_may_dangle(hir_id, *attr_span) } @@ -233,6 +285,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => { self.check_pass_by_value(attr_span, span, target) } + &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => { + self.check_rustc_std_internal_symbol(attr_span, span, target) + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -246,7 +301,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::no_sanitize, ..] => { self.check_no_sanitize(attr, span, target) } - [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), [sym::thread_local, ..] => self.check_thread_local(attr, span, target), [sym::doc, ..] => self.check_doc_attrs( attr, @@ -258,9 +312,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ), [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), - [sym::rustc_std_internal_symbol, ..] => { - self.check_rustc_std_internal_symbol(attr, span, target) - } [sym::rustc_no_implicit_autorefs, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } @@ -287,22 +338,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), - [sym::rustc_coinductive, ..] - | [sym::rustc_must_implement_one_of, ..] - | [sym::rustc_deny_explicit_impl, ..] - | [sym::rustc_do_not_implement_via_object, ..] - | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target), + [sym::rustc_must_implement_one_of, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target), [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), - [sym::rustc_allow_incoherent_impl, ..] => { - self.check_allow_incoherent_impl(attr, span, target) - } [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target), [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), - [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) @@ -312,9 +355,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::should_panic, ..] => { self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn) } - [sym::automatically_derived, ..] => { - self.check_generic_attr_unparsed(hir_id, attr, target, Target::Impl) - } [sym::proc_macro, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) } @@ -331,9 +371,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::coroutine, ..] => { self.check_coroutine(attr, target); } - [sym::type_const, ..] => { - self.check_type_const(hir_id,attr, target); - } [sym::linkage, ..] => self.check_linkage(attr, span, target), [ // ok @@ -346,11 +383,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_attr | sym::cfg_trace | sym::cfg_attr_trace - | sym::export_stable // handled in `check_export` // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) - | sym::pointee // FIXME(derive_coerce_pointee) - | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) | sym::instruction_set // broken on stable!!! | sym::windows_subsystem // broken on stable!!! | sym::patchable_function_entry // FIXME(patchable_function_entry) @@ -359,18 +393,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::prelude_import | sym::panic_handler | sym::allow_internal_unsafe - | sym::fundamental | sym::lang | sym::needs_allocator | sym::default_lib_allocator | sym::custom_mir, .. ] => {} - [name, ..] => { + [name, rest@..] => { match BUILTIN_ATTRIBUTE_MAP.get(name) { // checked below Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} Some(_) => { + if rest.len() > 0 && AttributeParser::<Late>::is_parsed_attribute(slice::from_ref(name)) { + // Check if we tried to use a builtin attribute as an attribute namespace, like `#[must_use::skip]`. + // This check is here to solve https://github.com/rust-lang/rust/issues/137590 + // An error is already produced for this case elsewhere + continue + } + // FIXME: differentiate between unstable and internal attributes just // like we do with features instead of just accepting `rustc_` // attributes by name. That should allow trimming the above list, too. @@ -442,7 +482,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ); } - /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl. + /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl and that it has no + /// arguments. fn check_do_not_recommend( &self, attr_span: Span, @@ -459,7 +500,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ) { self.tcx.emit_node_span_lint( - UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + MISPLACED_DIAGNOSTIC_ATTRIBUTES, hir_id, attr_span, errors::IncorrectDoNotRecommendLocation, @@ -467,7 +508,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } if !attr.is_word() { self.tcx.emit_node_span_lint( - UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + MALFORMED_DIAGNOSTIC_ATTRIBUTES, hir_id, attr_span, errors::DoNotRecommendDoesNotExpectArgs, @@ -479,7 +520,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) { if !matches!(target, Target::Trait) { self.tcx.emit_node_span_lint( - UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, + MISPLACED_DIAGNOSTIC_ATTRIBUTES, hir_id, attr_span, DiagnosticOnUnimplementedOnlyForTraits, @@ -640,9 +681,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { allowed_target: Target, ) { if target != allowed_target { - let path = attr.path(); - let path: Vec<_> = path.iter().map(|s| s.as_str()).collect(); - let attr_name = path.join("::"); + let attr_name = join_path_syms(attr.path()); self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, @@ -823,7 +862,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the `#[marker]` attribute on an `item` is valid. - fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_marker(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Trait => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an @@ -831,13 +870,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "marker"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "marker"); } _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { - attr_span: attr.span(), - defn_span: span, - }); + self.dcx() + .emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span: span }); } } } @@ -1123,9 +1160,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match item.kind { ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) if generics.params.len() != 0 => {} - ItemKind::Trait(_, _, _, generics, _, items) + ItemKind::Trait(_, _, _, _, generics, _, items) if generics.params.len() != 0 - || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {} + || items.iter().any(|item| { + matches!(self.tcx.def_kind(item.owner_id), DefKind::AssocTy) + }) => {} ItemKind::TyAlias(_, generics, _) if generics.params.len() != 0 => {} _ => { self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() }); @@ -1482,11 +1521,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) { + fn check_allow_incoherent_impl(&self, attr_span: Span, span: Span, target: Target) { match target { Target::Method(MethodKind::Inherent) => {} _ => { - self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span: attr.span(), span }); + self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span, span }); } } } @@ -1507,7 +1546,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span }); return; } - if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { + if find_attr!(attrs, AttributeKind::FfiConst(_)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span }); } @@ -1916,22 +1955,37 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the `#[align]` attributes on `item` are valid. - fn check_align(&self, span: Span, target: Target, align: Align, repr_span: Span) { + fn check_align( + &self, + span: Span, + hir_id: HirId, + target: Target, + align: Align, + attr_span: Span, + ) { match target { Target::Fn | Target::Method(_) | Target::ForeignFn => {} + Target::Field => { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr_span, + AlignOnFields { span }, + ); + } Target::Struct | Target::Union | Target::Enum => { self.dcx().emit_err(errors::AlignShouldBeReprAlign { - span: repr_span, + span: attr_span, item: target.name(), align_bytes: align.bytes(), }); } _ => { - self.dcx().emit_err(errors::AlignAttrApplication { hint_span: repr_span, span }); + self.dcx().emit_err(errors::AlignAttrApplication { hint_span: attr_span, span }); } } - self.check_align_value(align, repr_span); + self.check_align_value(align, attr_span); } /// Checks if the `#[repr]` attributes on `item` are valid. @@ -2214,13 +2268,52 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { + fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) { + match target { + // FIXME(staged_api): There's no reason we can't support more targets here. We're just + // being conservative to begin with. + Target::Fn | Target::Impl => {} + Target::ExternCrate + | Target::Use + | Target::Static + | Target::Const + | Target::Closure + | Target::Mod + | Target::ForeignMod + | Target::GlobalAsm + | Target::TyAlias + | Target::Enum + | Target::Variant + | Target::Struct + | Target::Field + | Target::Union + | Target::Trait + | Target::TraitAlias + | Target::Expression + | Target::Statement + | Target::Arm + | Target::AssocConst + | Target::Method(_) + | Target::AssocTy + | Target::ForeignFn + | Target::ForeignStatic + | Target::ForeignTy + | Target::GenericParam(_) + | Target::MacroDef + | Target::Param + | Target::PatField + | Target::ExprField + | Target::WherePredicate => { + self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span }); + } + } + } + + fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) { match target { Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {} _ => { - self.tcx - .dcx() - .emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span(), span }); + self.tcx.dcx().emit_err(errors::RustcStdInternalSymbol { attr_span, span }); } } } @@ -2234,11 +2327,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) { + fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) { match target { Target::ForeignFn | Target::ForeignStatic => {} _ => { - self.dcx().emit_err(errors::LinkOrdinal { attr_span: attr.span() }); + self.dcx().emit_err(errors::LinkOrdinal { attr_span }); } } } @@ -2509,7 +2602,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_type_const(&self, hir_id: HirId, attr: &Attribute, target: Target) { + fn check_type_const(&self, hir_id: HirId, attr_span: Span, target: Target) { let tcx = self.tcx; if target == Target::AssocConst && let parent = tcx.parent(hir_id.expect_owner().to_def_id()) @@ -2519,7 +2612,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } else { self.dcx() .struct_span_err( - attr.span(), + attr_span, "`#[type_const]` must only be applied to trait associated constants", ) .emit(); @@ -2800,7 +2893,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { // resolution for the attribute macro error. const ATTRS_TO_CHECK: &[Symbol] = &[ sym::macro_export, - sym::automatically_derived, sym::rustc_main, sym::derive, sym::test, @@ -2823,6 +2915,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { (*first_attr_span, sym::repr) } else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr { (*span, sym::path) + } else if let Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) = attr { + (*span, sym::automatically_derived) } else { continue; }; diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index f8f489d7d06..b1f4584c2a8 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -2,6 +2,7 @@ use std::iter; use std::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -14,7 +15,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Visibility, }; use rustc_session::config::CrateType; -use rustc_span::{Span, sym}; +use rustc_span::Span; use crate::errors::UnexportableItem; @@ -44,7 +45,7 @@ impl<'tcx> ExportableItemCollector<'tcx> { } fn item_is_exportable(&self, def_id: LocalDefId) -> bool { - let has_attr = self.tcx.has_attr(def_id, sym::export_stable); + let has_attr = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable); if !self.in_exportable_mod && !has_attr { return false; } @@ -80,7 +81,7 @@ impl<'tcx> ExportableItemCollector<'tcx> { fn walk_item_with_mod(&mut self, item: &'tcx hir::Item<'tcx>) { let def_id = item.hir_id().owner.def_id; let old_exportable_mod = self.in_exportable_mod; - if self.tcx.get_attr(def_id, sym::export_stable).is_some() { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable) { self.in_exportable_mod = true; } let old_seen_exportable_in_mod = std::mem::replace(&mut self.seen_exportable_in_mod, false); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index cdfd1a2b07e..d987041fe0e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -18,7 +18,7 @@ use rustc_hir::{self as hir, ImplItem, ImplItemKind, Node, PatKind, QPath, TyKin use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, AssocTag, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::DEAD_CODE; use rustc_session::lint::{self, LintExpectationId}; @@ -115,7 +115,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { + Res::Def( + DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias, + def_id, + ) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -415,8 +418,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { 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()); + if matches!(self.tcx.def_kind(trait_item.owner_id), DefKind::AssocTy) { + self.check_def_id(trait_item.owner_id.to_def_id()); } } intravisit::walk_item(self, item) @@ -482,7 +485,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { ) -> bool { 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 + DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => self .tcx .associated_item(local_def_id) .trait_item_def_id @@ -647,6 +650,31 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.in_pat = in_pat; } + + fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) { + if let Some(trait_def_id) = t.path.res.opt_def_id() + && let Some(segment) = t.path.segments.last() + && let Some(args) = segment.args + { + for constraint in args.constraints { + if let Some(local_def_id) = self + .tcx + .associated_items(trait_def_id) + .find_by_ident_and_kind( + self.tcx, + constraint.ident, + AssocTag::Const, + trait_def_id, + ) + .and_then(|item| item.def_id.as_local()) + { + self.worklist.push((local_def_id, ComesFromAllowExpect::No)); + } + } + } + + intravisit::walk_trait_ref(self, t); + } } fn has_allow_dead_code_or_lang_attr( @@ -744,18 +772,12 @@ fn check_item<'tcx>( { worklist.push((local_def_id, comes_from_allow)); } else if of_trait { - // 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)); - } + // 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)); } } } @@ -791,15 +813,14 @@ fn check_trait_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::TraitItemId, ) { - use hir::TraitItemKind::{Const, Fn}; - if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { - let trait_item = tcx.hir_trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) - && let Some(comes_from_allow) = - has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) - { - worklist.push((trait_item.owner_id.def_id, comes_from_allow)); - } + use hir::TraitItemKind::{Const, Fn, Type}; + + let trait_item = tcx.hir_trait_item(id); + if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..)) + && let Some(comes_from_allow) = + has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) + { + worklist.push((trait_item.owner_id.def_id, comes_from_allow)); } } @@ -1163,6 +1184,7 @@ impl<'tcx> DeadVisitor<'tcx> { } match self.tcx.def_kind(def_id) { DefKind::AssocConst + | DefKind::AssocTy | DefKind::AssocFn | DefKind::Fn | DefKind::Static { .. } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4ad615a2abf..37330c0ed6e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -604,6 +604,14 @@ pub(crate) struct NoMangle { pub span: Span, } +#[derive(LintDiagnostic)] +#[diag(passes_align_on_fields)] +#[warning] +pub(crate) struct AlignOnFields { + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_repr_conflicting, code = E0566)] pub(crate) struct ReprConflicting { @@ -679,6 +687,15 @@ pub(crate) struct RustcAllowConstFnUnstable { } #[derive(Diagnostic)] +#[diag(passes_rustc_unstable_feature_bound)] +pub(crate) struct RustcUnstableFeatureBound { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] pub(crate) struct RustcStdInternalSymbol { #[primary_span] diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index e38c7b2cbf1..6ee325dce03 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -467,9 +467,9 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_trait_item(self, ti) } - fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemRef) { - self.record("TraitItemRef", Some(ti.id.hir_id()), ti); - hir_visit::walk_trait_item_ref(self, ti) + fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemId) { + self.record("TraitItemId", Some(ti.hir_id()), ti); + hir_visit::walk_trait_item_ref(self, *ti) } fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) { @@ -480,14 +480,14 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_impl_item(self, ii) } - fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemRef) { - self.record("ForeignItemRef", Some(fi.id.hir_id()), fi); - hir_visit::walk_foreign_item_ref(self, fi) + fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemId) { + self.record("ForeignItemId", Some(fi.hir_id()), fi); + hir_visit::walk_foreign_item_ref(self, *fi) } - fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemRef) { - self.record("ImplItemRef", Some(ii.id.hir_id()), ii); - hir_visit::walk_impl_item_ref(self, ii) + fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemId) { + self.record("ImplItemId", Some(ii.hir_id()), ii); + hir_visit::walk_impl_item_ref(self, *ii) } fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) { diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 3088e189c20..7350c6a5a82 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -97,7 +97,7 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; -use rustc_span::{BytePos, Span, Symbol, sym}; +use rustc_span::{BytePos, Span, Symbol}; use tracing::{debug, instrument}; use self::LiveNodeKind::*; @@ -140,7 +140,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Don't run unused pass for #[derive()] let parent = tcx.local_parent(def_id); if let DefKind::Impl { .. } = tcx.def_kind(parent) - && tcx.has_attr(parent, sym::automatically_derived) + && find_attr!(tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) { return; } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 7e15267a953..b49e8118fe3 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -325,6 +325,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit(args); } } + GlobalAlloc::TypeId { ty, .. } => self.visit(ty), GlobalAlloc::Memory(alloc) => self.propagate_from_alloc(alloc), } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a30655d32a7..e5530d52686 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -802,12 +802,28 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability); + let unstable_feature_stab = + find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i) + .map(|i| i.as_slice()) + .unwrap_or_default(); + // 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 + // + // The exception is when there are both #[unstable_feature_bound(..)] and + // #![unstable(feature = "..", issue = "..")] that have the same symbol because + // that can effectively mark an impl as unstable. + // + // For example: + // ``` + // #[unstable_feature_bound(feat_foo)] + // #[unstable(feature = "feat_foo", issue = "none")] + // impl Foo for Bar {} + // ``` if let Some(( - Stability { level: attrs::StabilityLevel::Unstable { .. }, .. }, + Stability { level: attrs::StabilityLevel::Unstable { .. }, feature }, span, )) = stab { @@ -815,9 +831,21 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { c.visit_ty_unambig(self_ty); c.visit_trait_ref(t); + // Skip the lint if the impl is marked as unstable using + // #[unstable_feature_bound(..)] + let mut unstable_feature_bound_in_effect = false; + for (unstable_bound_feat_name, _) in unstable_feature_stab { + if *unstable_bound_feat_name == feature { + unstable_feature_bound_in_effect = true; + } + } + // do not lint when the trait isn't resolved, since resolution error should // be fixed first - if t.path.res != Res::Err && c.fully_stable { + if t.path.res != Res::Err + && c.fully_stable + && !unstable_feature_bound_in_effect + { self.tcx.emit_node_span_lint( INEFFECTIVE_UNSTABLE_TRAIT_IMPL, item.hir_id(), @@ -880,11 +908,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } for impl_item_ref in *items { - let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id); + let impl_item = self.tcx.associated_item(impl_item_ref.owner_id); if let Some(def_id) = impl_item.trait_item_def_id { // Pass `None` to skip deprecation warnings. - self.tcx.check_stability(def_id, None, impl_item_ref.span, None); + self.tcx.check_stability( + def_id, + None, + self.tcx.def_span(impl_item_ref.owner_id), + None, + ); } } } |
