about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-07-02 15:46:49 +0530
committerGitHub <noreply@github.com>2016-07-02 15:46:49 +0530
commit2c643bd4d0efd67665b2cb57ff485bcd79cce76d (patch)
treea2ea60fd65d9eda2be3954869d4d3d6bce483bb7 /src
parent7e07e31600d2b15697c2fffceb9d08c65af6a062 (diff)
parent84e874f0e0969b65e24e2705aac7604b79e387b0 (diff)
downloadrust-2c643bd4d0efd67665b2cb57ff485bcd79cce76d.tar.gz
rust-2c643bd4d0efd67665b2cb57ff485bcd79cce76d.zip
Rollup merge of #34531 - GuillaumeGomez:libsyntax_err_codes, r=jonathandturner
Add error codes in libsyntax

r? @jonathandturner

Fixes #34526
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/attr.rs105
-rw-r--r--src/libsyntax/diagnostic_list.rs54
-rw-r--r--src/libsyntax/feature_gate.rs17
-rw-r--r--src/libsyntax/lib.rs21
-rw-r--r--src/test/compile-fail/stability-attribute-sanity.rs49
5 files changed, 167 insertions, 79 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 3c88fb8f670..e01bd2a93aa 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -34,6 +34,27 @@ thread_local! {
     static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new())
 }
 
+enum AttrError {
+    MultipleItem(InternedString),
+    UnknownMetaItem(InternedString),
+    MissingSince,
+    MissingFeature,
+    MultipleStabilityLevels,
+}
+
+fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
+    match error {
+        AttrError::MultipleItem(item) => span_err!(diag, span, E0538,
+                                                   "multiple '{}' items", item),
+        AttrError::UnknownMetaItem(item) => span_err!(diag, span, E0541,
+                                                      "unknown meta item '{}'", item),
+        AttrError::MissingSince => span_err!(diag, span, E0542, "missing 'since'"),
+        AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"),
+        AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544,
+                                                        "multiple stability levels"),
+    }
+}
+
 pub fn mark_used(attr: &Attribute) {
     let AttrId(id) = attr.node.id;
     USED_ATTRS.with(|slot| {
@@ -303,10 +324,10 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
             if let s@Some(_) = attr.value_str() {
                 s
             } else {
-                diag.struct_span_err(attr.span,
-                                     "export_name attribute has invalid format")
-                    .help("use #[export_name=\"*\"]")
-                    .emit();
+                struct_span_err!(diag, attr.span, E0533,
+                                 "export_name attribute has invalid format")
+                                .help("use #[export_name=\"*\"]")
+                                .emit();
                 None
             }
         } else {
@@ -339,14 +360,16 @@ pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> In
             MetaItemKind::List(ref n, ref items) if n == "inline" => {
                 mark_used(attr);
                 if items.len() != 1 {
-                    diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
+                    diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
                     InlineAttr::None
                 } else if contains_name(&items[..], "always") {
                     InlineAttr::Always
                 } else if contains_name(&items[..], "never") {
                     InlineAttr::Never
                 } else {
-                    diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
+                    diagnostic.map(|d| {
+                        span_err!(d, (*items[0]).span, E0535, "invalid argument");
+                    });
                     InlineAttr::None
                 }
             }
@@ -374,13 +397,13 @@ pub fn cfg_matches(cfgs: &[P<MetaItem>], cfg: &ast::MetaItem,
             mis.iter().all(|mi| cfg_matches(cfgs, &mi, sess, features)),
         ast::MetaItemKind::List(ref pred, ref mis) if &pred[..] == "not" => {
             if mis.len() != 1 {
-                sess.span_diagnostic.span_err(cfg.span, "expected 1 cfg-pattern");
+                span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
                 return false;
             }
             !cfg_matches(cfgs, &mis[0], sess, features)
         }
         ast::MetaItemKind::List(ref pred, _) => {
-            sess.span_diagnostic.span_err(cfg.span, &format!("invalid predicate `{}`", pred));
+            span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", pred);
             false
         },
         ast::MetaItemKind::Word(_) | ast::MetaItemKind::NameValue(..) => {
@@ -446,15 +469,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
                 if item.is_some() {
-                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
-                                                             meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
                     *item = Some(v);
                     true
                 } else {
-                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    span_err!(diagnostic, meta.span, E0539, "incorrect meta item");
                     false
                 }
             };
@@ -462,7 +484,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             match tag {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
-                        diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
+                        span_err!(diagnostic, item_sp, E0540,
+                                  "multiple rustc_deprecated attributes");
                         break
                     }
 
@@ -473,8 +496,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "since" => if !get(meta, &mut since) { continue 'outer },
                             "reason" => if !get(meta, &mut reason) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -488,18 +511,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'reason'");
+                            span_err!(diagnostic, attr.span(), E0543, "missing 'reason'");
                             continue
                         }
                     }
                 }
                 "unstable" => {
                     if stab.is_some() {
-                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
                         break
                     }
 
@@ -512,8 +535,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "reason" => if !get(meta, &mut reason) { continue 'outer },
                             "issue" => if !get(meta, &mut issue) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -528,7 +551,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                         if let Ok(issue) = issue.parse() {
                                             issue
                                         } else {
-                                            diagnostic.span_err(attr.span(), "incorrect 'issue'");
+                                            span_err!(diagnostic, attr.span(), E0545,
+                                                      "incorrect 'issue'");
                                             continue
                                         }
                                     }
@@ -538,18 +562,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'issue'");
+                            span_err!(diagnostic, attr.span(), E0547, "missing 'issue'");
                             continue
                         }
                     }
                 }
                 "stable" => {
                     if stab.is_some() {
-                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
                         break
                     }
 
@@ -560,8 +584,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             "feature" => if !get(meta, &mut feature) { continue 'outer },
                             "since" => if !get(meta, &mut since) { continue 'outer },
                             _ => {
-                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                        meta.name()));
+                                handle_errors(diagnostic, meta.span,
+                                              AttrError::UnknownMetaItem(meta.name()));
                                 continue 'outer
                             }
                         }
@@ -578,11 +602,11 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             })
                         }
                         (None, _) => {
-                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingFeature);
                             continue
                         }
                         _ => {
-                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            handle_errors(diagnostic, attr.span(), AttrError::MissingSince);
                             continue
                         }
                     }
@@ -590,7 +614,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 _ => unreachable!()
             }
         } else {
-            diagnostic.span_err(attr.span(), "incorrect stability attribute type");
+            span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
             continue
         }
     }
@@ -603,8 +627,9 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             }
             stab.rustc_depr = Some(rustc_depr);
         } else {
-            diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
-                                          either stable or unstable attribute");
+            span_err!(diagnostic, item_sp, E0549,
+                      "rustc_deprecated attribute must be paired with \
+                       either stable or unstable attribute");
         }
     }
 
@@ -627,22 +652,21 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
         mark_used(attr);
 
         if depr.is_some() {
-            diagnostic.span_err(item_sp, "multiple deprecated attributes");
+            span_err!(diagnostic, item_sp, E0550, "multiple deprecated attributes");
             break
         }
 
         depr = if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
                 if item.is_some() {
-                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
-                                                             meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
                     *item = Some(v);
                     true
                 } else {
-                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    span_err!(diagnostic, meta.span, E0551, "incorrect meta item");
                     false
                 }
             };
@@ -654,8 +678,8 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
                     "since" => if !get(meta, &mut since) { continue 'outer },
                     "note" => if !get(meta, &mut note) { continue 'outer },
                     _ => {
-                        diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
-                                                                meta.name()));
+                        handle_errors(diagnostic, meta.span,
+                                      AttrError::UnknownMetaItem(meta.name()));
                         continue 'outer
                     }
                 }
@@ -689,7 +713,7 @@ pub fn require_unique_names(diagnostic: &Handler, metas: &[P<MetaItem>]) {
 
         if !set.insert(name.clone()) {
             panic!(diagnostic.span_fatal(meta.span,
-                                  &format!("duplicate meta item `{}`", name)));
+                                         &format!("duplicate meta item `{}`", name)));
         }
     }
 }
@@ -718,8 +742,8 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                                 Some(ity) => Some(ReprInt(item.span, ity)),
                                 None => {
                                     // Not a word we recognize
-                                    diagnostic.span_err(item.span,
-                                                        "unrecognized representation hint");
+                                    span_err!(diagnostic, item.span, E0552,
+                                              "unrecognized representation hint");
                                     None
                                 }
                             }
@@ -731,7 +755,8 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         }
                     }
                     // Not a word:
-                    _ => diagnostic.span_err(item.span, "unrecognized enum representation hint")
+                    _ => span_err!(diagnostic, item.span, E0553,
+                                   "unrecognized enum representation hint"),
                 }
             }
         }
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
new file mode 100644
index 00000000000..eb30657bd56
--- /dev/null
+++ b/src/libsyntax/diagnostic_list.rs
@@ -0,0 +1,54 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_snake_case)]
+
+// Error messages for EXXXX errors.
+// Each message should start and end with a new line, and be wrapped to 80 characters.
+// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
+register_long_diagnostics! {
+
+E0533: r##"
+```compile_fail,E0533
+#[export_name]
+pub fn something() {}
+
+fn main() {}
+```
+"##,
+
+}
+
+register_diagnostics! {
+    E0534, // expected one argument
+    E0535, // invalid argument
+    E0536, // expected 1 cfg-pattern
+    E0537, // invalid predicate
+    E0538, // multiple [same] items
+    E0539, // incorrect meta item
+    E0540, // multiple rustc_deprecated attributes
+    E0541, // unknown meta item
+    E0542, // missing 'since'
+    E0543, // missing 'reason'
+    E0544, // multiple stability levels
+    E0545, // incorrect 'issue'
+    E0546, // missing 'feature'
+    E0547, // missing 'issue'
+    E0548, // incorrect stability attribute type
+    E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
+    E0550, // multiple deprecated attributes
+    E0551, // incorrect meta item
+    E0552, // unrecognized representation hint
+    E0553, // unrecognized enum representation hint
+    E0554, // #[feature] may not be used on the [] release channel
+    E0555, // malformed feature attribute, expected #![feature(...)]
+    E0556, // malformed feature, expected just one word
+    E0557, // feature has been removed
+}
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index d6476fdb2f0..27485ee65fc 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1103,17 +1103,16 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
 
         match attr.meta_item_list() {
             None => {
-                span_handler.span_err(attr.span, "malformed feature attribute, \
-                                                  expected #![feature(...)]");
+                span_err!(span_handler, attr.span, E0555,
+                          "malformed feature attribute, expected #![feature(...)]");
             }
             Some(list) => {
                 for mi in list {
                     let name = match mi.node {
                         ast::MetaItemKind::Word(ref word) => (*word).clone(),
                         _ => {
-                            span_handler.span_err(mi.span,
-                                                  "malformed feature, expected just \
-                                                   one word");
+                            span_err!(span_handler, mi.span, E0556,
+                                      "malformed feature, expected just one word");
                             continue
                         }
                     };
@@ -1123,7 +1122,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
                     }
                     else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
                         .find(|& &(n, _, _)| name == n) {
-                        span_handler.span_err(mi.span, "feature has been removed");
+                        span_err!(span_handler, mi.span, E0557, "feature has been removed");
                     }
                     else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
                         .find(|& &(n, _, _)| name == n) {
@@ -1179,9 +1178,9 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
         for attr in &krate.attrs {
             if attr.check_name("feature") {
                 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
-                let ref msg = format!("#[feature] may not be used on the {} release channel",
-                                      release_channel);
-                span_handler.span_err(attr.span, msg);
+                span_err!(span_handler, attr.span, E0554,
+                          "#[feature] may not be used on the {} release channel",
+                          release_channel);
             }
         }
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 652cf68db07..8febf1c49ec 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -33,6 +33,7 @@
 #![feature(str_escape)]
 #![feature(unicode)]
 #![feature(question_mark)]
+#![feature(rustc_diagnostic_macros)]
 
 extern crate serialize;
 extern crate term;
@@ -66,6 +67,18 @@ macro_rules! panictry {
     })
 }
 
+#[macro_use]
+pub mod diagnostics {
+    #[macro_use]
+    pub mod macros;
+    pub mod plugin;
+    pub mod metadata;
+}
+
+// NB: This module needs to be declared first so diagnostics are
+// registered before they are used.
+pub mod diagnostic_list;
+
 pub mod util {
     pub mod interner;
     pub mod lev_distance;
@@ -80,12 +93,6 @@ pub mod util {
     pub use self::thin_vec::ThinVec;
 }
 
-pub mod diagnostics {
-    pub mod macros;
-    pub mod plugin;
-    pub mod metadata;
-}
-
 pub mod json;
 
 pub mod syntax {
@@ -130,3 +137,5 @@ pub mod ext {
         pub mod macro_rules;
     }
 }
+
+// __build_diagnostic_array! { libsyntax, DIAGNOSTICS }
diff --git a/src/test/compile-fail/stability-attribute-sanity.rs b/src/test/compile-fail/stability-attribute-sanity.rs
index 8c7c0c275db..d35f2cbb584 100644
--- a/src/test/compile-fail/stability-attribute-sanity.rs
+++ b/src/test/compile-fail/stability-attribute-sanity.rs
@@ -15,83 +15,84 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 mod bogus_attribute_types_1 {
-    #[stable(feature = "a", since = "a", reason)] //~ ERROR unknown meta item 'reason'
+    #[stable(feature = "a", since = "a", reason)] //~ ERROR unknown meta item 'reason' [E0541]
     fn f1() { }
 
-    #[stable(feature = "a", since)] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since)] //~ ERROR incorrect meta item [E0539]
     fn f2() { }
 
-    #[stable(feature, since = "a")] //~ ERROR incorrect meta item
+    #[stable(feature, since = "a")] //~ ERROR incorrect meta item [E0539]
     fn f3() { }
 
-    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item [E0539]
     fn f5() { }
 
-    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item
+    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item [E0539]
     fn f6() { }
 }
 
 mod bogus_attribute_types_2 {
-    #[unstable] //~ ERROR incorrect stability attribute type
+    #[unstable] //~ ERROR incorrect stability attribute type [E0548]
     fn f1() { }
 
-    #[unstable = "a"] //~ ERROR incorrect stability attribute type
+    #[unstable = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f2() { }
 
-    #[stable] //~ ERROR incorrect stability attribute type
+    #[stable] //~ ERROR incorrect stability attribute type [E0548]
     fn f3() { }
 
-    #[stable = "a"] //~ ERROR incorrect stability attribute type
+    #[stable = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f4() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated] //~ ERROR incorrect stability attribute type
+    #[rustc_deprecated] //~ ERROR incorrect stability attribute type [E0548]
     fn f5() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated = "a"] //~ ERROR incorrect stability attribute type
+    #[rustc_deprecated = "a"] //~ ERROR incorrect stability attribute type [E0548]
     fn f6() { }
 }
 
 mod missing_feature_names {
-    #[unstable(issue = "0")] //~ ERROR missing 'feature'
+    #[unstable(issue = "0")] //~ ERROR missing 'feature' [E0546]
     fn f1() { }
 
-    #[unstable(feature = "a")] //~ ERROR missing 'issue'
+    #[unstable(feature = "a")] //~ ERROR missing 'issue' [E0547]
     fn f2() { }
 
-    #[stable(since = "a")] //~ ERROR missing 'feature'
+    #[stable(since = "a")] //~ ERROR missing 'feature' [E0546]
     fn f3() { }
 }
 
 mod missing_version {
-    #[stable(feature = "a")] //~ ERROR missing 'since'
+    #[stable(feature = "a")] //~ ERROR missing 'since' [E0542]
     fn f1() { }
 
     #[stable(feature = "a", since = "b")]
-    #[rustc_deprecated(reason = "a")] //~ ERROR missing 'since'
+    #[rustc_deprecated(reason = "a")] //~ ERROR missing 'since' [E0542]
     fn f2() { }
 }
 
 #[unstable(feature = "a", issue = "0")]
-#[stable(feature = "a", since = "b")]
-fn multiple1() { } //~ ERROR multiple stability levels
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple1() { }
 
 #[unstable(feature = "a", issue = "0")]
-#[unstable(feature = "a", issue = "0")]
-fn multiple2() { } //~ ERROR multiple stability levels
+#[unstable(feature = "a", issue = "0")] //~ ERROR multiple stability levels [E0544]
+fn multiple2() { }
 
 #[stable(feature = "a", since = "b")]
-#[stable(feature = "a", since = "b")]
-fn multiple3() { } //~ ERROR multiple stability levels
+#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544]
+fn multiple3() { }
 
 #[stable(feature = "a", since = "b")]
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_deprecated(since = "b", reason = "text")]
-fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes
+fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
 //~^ ERROR Invalid stability or deprecation version found
 
 #[rustc_deprecated(since = "a", reason = "text")]
-fn deprecated_without_unstable_or_stable() { } //~ ERROR rustc_deprecated attribute must be paired
+fn deprecated_without_unstable_or_stable() { }
+//~^ ERROR rustc_deprecated attribute must be paired with either stable or unstable attribute
 
 fn main() { }