]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/hir/check_attr.rs
Implement RFC 2645 (transparent enums and unions)
[rust.git] / src / librustc / hir / check_attr.rs
index 4c527f80d0f5d7593401c2891cfdeda08b08b8fa..f7d1094b3a2d1407c14c471f85a7b0d37afa9760 100644 (file)
@@ -12,6 +12,7 @@
 use crate::hir::def_id::DefId;
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use std::fmt::{self, Display};
+use syntax::symbol::sym;
 use syntax_pos::Span;
 
 #[derive(Copy, Clone, PartialEq)]
@@ -95,18 +96,18 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     fn check_attributes(&self, item: &hir::Item, target: Target) {
         if target == Target::Fn || target == Target::Const {
             self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id_from_hir_id(item.hir_id));
-        } else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
+        } else if let Some(a) = item.attrs.iter().find(|a| a.check_name(sym::target_feature)) {
             self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
                 .span_label(item.span, "not a function")
                 .emit();
         }
 
         for attr in &item.attrs {
-            if attr.check_name("inline") {
+            if attr.check_name(sym::inline) {
                 self.check_inline(attr, &item.span, target)
-            } else if attr.check_name("non_exhaustive") {
+            } else if attr.check_name(sym::non_exhaustive) {
                 self.check_non_exhaustive(attr, item, target)
-            } else if attr.check_name("marker") {
+            } else if attr.check_name(sym::marker) {
                 self.check_marker(attr, item, target)
             }
         }
@@ -166,7 +167,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
         // ```
         let hints: Vec<_> = item.attrs
             .iter()
-            .filter(|attr| attr.check_name("repr"))
+            .filter(|attr| attr.check_name(sym::repr))
             .filter_map(|attr| attr.meta_item_list())
             .flatten()
             .collect();
@@ -177,18 +178,15 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
         let mut is_transparent = false;
 
         for hint in &hints {
-            let (article, allowed_targets) = match hint.name_or_empty().get() {
-                name @ "C" | name @ "align" => {
-                    is_c |= name == "C";
-                    if target != Target::Struct &&
-                            target != Target::Union &&
-                            target != Target::Enum {
-                                ("a", "struct, enum or union")
-                    } else {
-                        continue
+            let (article, allowed_targets) = match hint.name_or_empty() {
+                name @ sym::C | name @ sym::align => {
+                    is_c |= name == sym::C;
+                    match target {
+                        Target::Struct | Target::Union | Target::Enum => continue,
+                        _ => ("a", "struct, enum, or union"),
                     }
                 }
-                "packed" => {
+                sym::packed => {
                     if target != Target::Struct &&
                             target != Target::Union {
                                 ("a", "struct or union")
@@ -196,7 +194,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
                         continue
                     }
                 }
-                "simd" => {
+                sym::simd => {
                     is_simd = true;
                     if target != Target::Struct {
                         ("a", "struct")
@@ -204,17 +202,16 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
                         continue
                     }
                 }
-                "transparent" => {
+                sym::transparent => {
                     is_transparent = true;
-                    if target != Target::Struct {
-                        ("a", "struct")
-                    } else {
-                        continue
+                    match target {
+                        Target::Struct | Target::Union | Target::Enum => continue,
+                        _ => ("a", "struct, enum, or union"),
                     }
                 }
-                "i8"  | "u8"  | "i16" | "u16" |
-                "i32" | "u32" | "i64" | "u64" |
-                "isize" | "usize" => {
+                sym::i8  | sym::u8  | sym::i16 | sym::u16 |
+                sym::i32 | sym::u32 | sym::i64 | sym::u64 |
+                sym::isize | sym::usize => {
                     int_reprs += 1;
                     if target != Target::Enum {
                         ("an", "enum")
@@ -240,7 +237,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
         if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
             span_err!(self.tcx.sess, hint_spans, E0692,
-                      "transparent struct cannot have other repr hints");
+                      "transparent {} cannot have other repr hints", target);
         }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
@@ -268,15 +265,15 @@ fn check_stmt_attributes(&self, stmt: &hir::Stmt) {
         // When checking statements ignore expressions, they will be checked later
         if let hir::StmtKind::Local(ref l) = stmt.node {
             for attr in l.attrs.iter() {
-                if attr.check_name("inline") {
+                if attr.check_name(sym::inline) {
                     self.check_inline(attr, &stmt.span, Target::Statement);
                 }
-                if attr.check_name("repr") {
+                if attr.check_name(sym::repr) {
                     self.emit_repr_error(
                         attr.span,
                         stmt.span,
                         "attribute should not be applied to a statement",
-                        "not a struct, enum or union",
+                        "not a struct, enum, or union",
                     );
                 }
             }
@@ -289,15 +286,15 @@ fn check_expr_attributes(&self, expr: &hir::Expr) {
             _ => Target::Expression,
         };
         for attr in expr.attrs.iter() {
-            if attr.check_name("inline") {
+            if attr.check_name(sym::inline) {
                 self.check_inline(attr, &expr.span, target);
             }
-            if attr.check_name("repr") {
+            if attr.check_name(sym::repr) {
                 self.emit_repr_error(
                     attr.span,
                     expr.span,
                     "attribute should not be applied to an expression",
-                    "not defining a struct, enum or union",
+                    "not defining a struct, enum, or union",
                 );
             }
         }
@@ -305,7 +302,7 @@ fn check_expr_attributes(&self, expr: &hir::Expr) {
 
     fn check_used(&self, item: &hir::Item, target: Target) {
         for attr in &item.attrs {
-            if attr.check_name("used") && target != Target::Static {
+            if attr.check_name(sym::used) && target != Target::Static {
                 self.tcx.sess
                     .span_err(attr.span, "attribute must be applied to a `static` variable");
             }