about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNathan Stocks <cleancut@github.com>2022-10-02 14:34:10 -0600
committerNathan Stocks <cleancut@github.com>2022-10-07 13:19:27 -0600
commit3fe8e004e99b4b2dd616210d5c7e4d211ab25043 (patch)
tree6f246f93656f88379e1f2f03c3a24d2bcfe686a1
parenta7aa1850b2de87e31ffa07df6f4d47e0a5f7b01e (diff)
downloadrust-3fe8e004e99b4b2dd616210d5c7e4d211ab25043.tar.gz
rust-3fe8e004e99b4b2dd616210d5c7e4d211ab25043.zip
migrate the rest of check_attr.rs to translateable diagnostics
-rw-r--r--compiler/rustc_error_messages/locales/en-US/passes.ftl36
-rw-r--r--compiler/rustc_passes/src/check_attr.rs95
-rw-r--r--compiler/rustc_passes/src/errors.rs41
3 files changed, 110 insertions, 62 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 2308c7b2453..217a05b4364 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -564,3 +564,39 @@ passes_useless_assignment =
         [true] field
         *[false] variable
     } of type `{$ty}` to itself
+
+passes_only_has_effect_on =
+    `#[{$attr_name}]` only has an effect on {$target_name ->
+        [function] functions
+        [module] modules
+        [implementation_block] implementation blocks
+        *[unspecified] (unspecified--this is a compiler bug)
+    }
+
+passes_object_lifetime_err =
+    {$repr}
+
+passes_unrecognized_repr_hint =
+    unrecognized representation hint
+    .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+
+passes_attribute_should_be_applied_to =
+    attribute should be applied to {$what ->
+        [enum] an enum
+        [struct] a struct
+        [struct-union] a struct or union
+        [struct-enum-union] a struct, enum, or union
+        [struct-enum-function-union] a struct, enum, function, or union
+        *[unspecified] (unspecified--this is a compiler bug)
+    }
+    .label = not {$what ->
+        [enum] an enum
+        [struct] a struct
+        [struct-union] a struct or union
+        [struct-enum-union] a struct, enum, or union
+        [struct-enum-function-union] a struct, enum, function, or union
+        *[unspecified] (unspecified--this is a compiler bug)
+    }
+
+passes_transparent_incompatible =
+    transparent {$target} cannot have other repr hints
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 18e1233fa84..33eb57fe769 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,10 +4,13 @@
 //! conflicts between multiple such attributes attached to the same
 //! item.
 
-use crate::errors::{self, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel};
+use crate::errors::{
+    self, AttributeShouldBeAppliedTo, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel,
+    ObjectLifetimeErr, OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
+};
 use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan};
+use rustc_errors::{fluent, Applicability, MultiSpan};
 use rustc_expand::base::resolve_path;
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
@@ -164,17 +167,17 @@ impl CheckAttrVisitor<'_> {
                 sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
                 sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
                 sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
-                sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
+                sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
                 sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
                 sym::macro_export => self.check_macro_export(hir_id, attr, target),
                 sym::ignore | sym::should_panic | sym::proc_macro_derive => {
-                    self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
+                    self.check_generic_attr(hir_id, attr, target, Target::Fn)
                 }
                 sym::automatically_derived => {
-                    self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
+                    self.check_generic_attr(hir_id, attr, target, Target::Impl)
                 }
                 sym::no_implicit_prelude => {
-                    self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
+                    self.check_generic_attr(hir_id, attr, target, Target::Mod)
                 }
                 sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
                 _ => {}
@@ -351,31 +354,17 @@ impl CheckAttrVisitor<'_> {
         hir_id: HirId,
         attr: &Attribute,
         target: Target,
-        allowed_targets: &[Target],
+        allowed_target: Target,
     ) {
-        if !allowed_targets.iter().any(|t| t == &target) {
-            let name = attr.name_or_empty();
-            let mut i = allowed_targets.iter();
-            // Pluralize
-            let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
-            let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
-                if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
-                    b.push_str(", and ");
-                } else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
-                    b.push_str(" and ");
-                } else {
-                    b.push_str(", ");
-                }
-                // Pluralize
-                b.push_str(&(allowed_target.to_string() + "s"));
-                b
-            });
-            self.tcx.struct_span_lint_hir(
+        if target != allowed_target {
+            self.tcx.emit_spanned_lint(
                 UNUSED_ATTRIBUTES,
                 hir_id,
                 attr.span,
-                &format!("`#[{name}]` only has an effect on {}", supported_names),
-                |lint| lint,
+                OnlyHasEffectOn {
+                    attr_name: attr.name_or_empty(),
+                    target_name: allowed_target.name().replace(" ", "_"),
+                },
             );
         }
     }
@@ -432,7 +421,7 @@ impl CheckAttrVisitor<'_> {
                     ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
                     ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
                 };
-                tcx.sess.span_err(p.span, &repr);
+                tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
             }
         }
     }
@@ -1605,12 +1594,12 @@ impl CheckAttrVisitor<'_> {
                 continue;
             }
 
-            let (article, allowed_targets) = match hint.name_or_empty() {
+            let what = match hint.name_or_empty() {
                 sym::C => {
                     is_c = true;
                     match target {
                         Target::Struct | Target::Union | Target::Enum => continue,
-                        _ => ("a", "struct, enum, or union"),
+                        _ => "struct-enum-union",
                     }
                 }
                 sym::align => {
@@ -1626,12 +1615,12 @@ impl CheckAttrVisitor<'_> {
 
                     match target {
                         Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
-                        _ => ("a", "struct, enum, function, or union"),
+                        _ => "struct-enum-function-union",
                     }
                 }
                 sym::packed => {
                     if target != Target::Struct && target != Target::Union {
-                        ("a", "struct or union")
+                        "struct-union"
                     } else {
                         continue;
                     }
@@ -1639,7 +1628,7 @@ impl CheckAttrVisitor<'_> {
                 sym::simd => {
                     is_simd = true;
                     if target != Target::Struct {
-                        ("a", "struct")
+                        "struct"
                     } else {
                         continue;
                     }
@@ -1648,7 +1637,7 @@ impl CheckAttrVisitor<'_> {
                     is_transparent = true;
                     match target {
                         Target::Struct | Target::Union | Target::Enum => continue,
-                        _ => ("a", "struct, enum, or union"),
+                        _ => "struct-enum-union",
                     }
                 }
                 sym::i8
@@ -1665,35 +1654,22 @@ impl CheckAttrVisitor<'_> {
                 | sym::usize => {
                     int_reprs += 1;
                     if target != Target::Enum {
-                        ("an", "enum")
+                        "enum"
                     } else {
                         continue;
                     }
                 }
                 _ => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        hint.span(),
-                        E0552,
-                        "unrecognized representation hint"
-                    )
-                    .help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
-                          `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
-                    .emit();
-
+                    self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
                     continue;
                 }
             };
 
-            struct_span_err!(
-                self.tcx.sess,
-                hint.span(),
-                E0517,
-                "{}",
-                &format!("attribute should be applied to {article} {allowed_targets}")
-            )
-            .span_label(span, &format!("not {article} {allowed_targets}"))
-            .emit();
+            self.tcx.sess.emit_err(AttributeShouldBeAppliedTo {
+                hint_span: hint.span(),
+                span,
+                what,
+            });
         }
 
         // Just point at all repr hints if there are any incompatibilities.
@@ -1703,14 +1679,9 @@ impl CheckAttrVisitor<'_> {
         // Error on repr(transparent, <anything else>).
         if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
-            struct_span_err!(
-                self.tcx.sess,
-                hint_spans,
-                E0692,
-                "transparent {} cannot have other repr hints",
-                target
-            )
-            .emit();
+            self.tcx
+                .sess
+                .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
         }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index ba1d4472e34..4f8c3ed6002 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1272,3 +1272,44 @@ pub struct UselessAssignment<'a> {
     pub is_field_assign: bool,
     pub ty: Ty<'a>,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(passes::only_has_effect_on)]
+pub struct OnlyHasEffectOn {
+    pub attr_name: Symbol,
+    pub target_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes::object_lifetime_err)]
+pub struct ObjectLifetimeErr {
+    #[primary_span]
+    pub span: Span,
+    pub repr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes::unrecognized_repr_hint, code = "E0552")]
+#[help]
+pub struct UnrecognizedReprHint {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes::attribute_should_be_applied_to, code = "E0517")]
+pub struct AttributeShouldBeAppliedTo<'a> {
+    #[primary_span]
+    pub hint_span: Span,
+    #[label]
+    pub span: Span,
+    pub what: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes::transparent_incompatible, code = "E0692")]
+pub struct TransparentIncompatible {
+    #[primary_span]
+    pub hint_spans: Vec<Span>,
+    pub target: String,
+}