X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_passes%2Fsrc%2Fcheck_attr.rs;h=e1ab4ba81ae47246c67592972638cd8548f6e947;hb=985ae0b55bf9bc2e2926f75a57578a32b982b10d;hp=85add83f88bf72f734b99be2c04929b4624ad933;hpb=32d3276561e88bfdf92cc483cff842a24fdd4b37;p=rust.git diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 85add83f88b..e1ab4ba81ae 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; use rustc_ast::{Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_errors::{pluralize, struct_span_err}; +use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -69,55 +69,48 @@ fn check_attributes( let mut is_valid = true; let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - is_valid &= if self.tcx.sess.check_name(attr, sym::inline) { - self.check_inline(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::non_exhaustive) { - self.check_non_exhaustive(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::marker) { - self.check_marker(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::target_feature) { - self.check_target_feature(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::track_caller) { - self.check_track_caller(hir_id, &attr.span, attrs, span, target) - } else if self.tcx.sess.check_name(attr, sym::doc) { - self.check_doc_attrs(attr, hir_id, target) - } else if self.tcx.sess.check_name(attr, sym::no_link) { - self.check_no_link(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::export_name) { - self.check_export_name(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_args_required_const) { - self.check_rustc_args_required_const(&attr, span, target, item) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_start) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_layout_scalar_valid_range_end) { - self.check_rustc_layout_scalar_valid_range(&attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::allow_internal_unstable) { - self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) - } else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) { - self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::naked) { - self.check_naked(hir_id, attr, span, target) - } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) { - self.check_rustc_legacy_const_generics(&attr, span, target, item) - } else if self.tcx.sess.check_name(attr, sym::rustc_clean) - || self.tcx.sess.check_name(attr, sym::rustc_dirty) - || self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) - || self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need) - { - self.check_rustc_dirty_clean(&attr) - } else { - // lint-only checks - if self.tcx.sess.check_name(attr, sym::cold) { - self.check_cold(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_name) { - self.check_link_name(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::link_section) { - self.check_link_section(hir_id, attr, span, target); - } else if self.tcx.sess.check_name(attr, sym::no_mangle) { - self.check_no_mangle(hir_id, attr, span, target); + is_valid &= match attr.name_or_empty() { + sym::inline => self.check_inline(hir_id, attr, span, target), + sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), + sym::marker => self.check_marker(hir_id, attr, span, target), + sym::target_feature => self.check_target_feature(hir_id, attr, span, target), + sym::track_caller => { + self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - true + sym::doc => self.check_doc_attrs(attr, hir_id, target), + sym::no_link => self.check_no_link(hir_id, &attr, span, target), + sym::export_name => self.check_export_name(hir_id, &attr, span, target), + sym::rustc_args_required_const => { + self.check_rustc_args_required_const(&attr, span, target, item) + } + sym::rustc_layout_scalar_valid_range_start + | sym::rustc_layout_scalar_valid_range_end => { + self.check_rustc_layout_scalar_valid_range(&attr, span, target) + } + sym::allow_internal_unstable => { + self.check_allow_internal_unstable(hir_id, &attr, span, target, &attrs) + } + sym::rustc_allow_const_fn_unstable => { + self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target) + } + 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) + } + sym::rustc_clean + | sym::rustc_dirty + | sym::rustc_if_this_changed + | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr), + _ => true, }; + // lint-only checks + match attr.name_or_empty() { + sym::cold => self.check_cold(hir_id, attr, span, target), + sym::link_name => self.check_link_name(hir_id, attr, span, target), + sym::link_section => self.check_link_section(hir_id, attr, span, target), + sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), + _ => {} + } } if !is_valid { @@ -648,10 +641,10 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo | sym::masked | sym::no_default_passes | sym::no_inline + | sym::notable_trait | sym::passes | sym::plugins | sym::primitive - | sym::spotlight | sym::test => {} _ => { @@ -660,11 +653,23 @@ fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bo hir_id, i_meta.span, |lint| { - let msg = format!( + let mut diag = lint.build(&format!( "unknown `doc` attribute `{}`", rustc_ast_pretty::pprust::path_to_string(&i_meta.path), - ); - lint.build(&msg).emit(); + )); + if i_meta.has_name(sym::spotlight) { + diag.note( + "`doc(spotlight)` was renamed to `doc(notable_trait)`", + ); + diag.span_suggestion_short( + i_meta.span, + "use `notable_trait` instead", + String::from("notable_trait"), + Applicability::MachineApplicable, + ); + diag.note("`doc(spotlight)` is now a no-op"); + } + diag.emit(); }, ); is_valid = false; @@ -1104,7 +1109,7 @@ fn check_repr( // ``` let hints: Vec<_> = attrs .iter() - .filter(|attr| self.tcx.sess.check_name(attr, sym::repr)) + .filter(|attr| attr.has_name(sym::repr)) .filter_map(|attr| attr.meta_item_list()) .flatten() .collect(); @@ -1115,17 +1120,41 @@ fn check_repr( let mut is_transparent = false; for hint in &hints { + if !hint.is_meta_item() { + struct_span_err!( + self.tcx.sess, + hint.span(), + E0565, + "meta item in `repr` must be an identifier" + ) + .emit(); + continue; + } + let (article, allowed_targets) = match hint.name_or_empty() { - _ if !matches!(target, Target::Struct | Target::Enum | Target::Union) => { - ("a", "struct, enum, or union") - } - name @ sym::C | name @ sym::align => { - is_c |= name == sym::C; + sym::C => { + is_c = true; match target { Target::Struct | Target::Union | Target::Enum => continue, _ => ("a", "struct, enum, or union"), } } + sym::align => { + if let (Target::Fn, true) = (target, !self.tcx.features().fn_align) { + feature_err( + &self.tcx.sess.parse_sess, + sym::fn_align, + hint.span(), + "`repr(align)` attributes on functions are unstable", + ) + .emit(); + } + + match target { + Target::Struct | Target::Union | Target::Enum | Target::Fn => continue, + _ => ("a", "struct, enum, function, or union"), + } + } sym::packed => { if target != Target::Struct && target != Target::Union { ("a", "struct or union") @@ -1182,7 +1211,17 @@ fn check_repr( continue; } } - _ => continue, + _ => { + struct_span_err!( + self.tcx.sess, + hint.span(), + E0552, + "unrecognized representation hint" + ) + .emit(); + + continue; + } }; struct_span_err!( @@ -1241,7 +1280,7 @@ fn check_repr( fn check_used(&self, attrs: &'hir [Attribute], target: Target) { for attr in attrs { - if self.tcx.sess.check_name(attr, sym::used) && target != Target::Static { + if attr.has_name(sym::used) && target != Target::Static { self.tcx .sess .span_err(attr.span, "attribute must be applied to a `static` variable");