diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 08c7c617a7bef..7230a2922c420 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -592,81 +592,86 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let diagnostic = &sess.span_diagnostic; 'outer: for attr in attrs_iter { - if attr.path != "deprecated" { - continue + if !attr.check_name("deprecated") { + continue; } - mark_used(attr); - if depr.is_some() { 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| { - if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); - return false - } - if let Some(v) = meta.value_str() { - *item = Some(v); - true - } else { - if let Some(lit) = meta.name_value_literal() { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "literal in `deprecated` \ - value must be a string", - lit.node.is_bytestr() - ), - ); - } else { - span_err!(diagnostic, meta.span, E0551, "incorrect meta item"); + let meta = attr.meta().unwrap(); + depr = match &meta.node { + MetaItemKind::Word => Some(Deprecation { since: None, note: None }), + MetaItemKind::NameValue(..) => { + meta.value_str().map(|note| { + Deprecation { since: None, note: Some(note) } + }) + } + MetaItemKind::List(list) => { + let get = |meta: &MetaItem, item: &mut Option| { + if item.is_some() { + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); + return false } + if let Some(v) = meta.value_str() { + *item = Some(v); + true + } else { + if let Some(lit) = meta.name_value_literal() { + handle_errors( + sess, + lit.span, + AttrError::UnsupportedLiteral( + "literal in `deprecated` \ + value must be a string", + lit.node.is_bytestr() + ), + ); + } else { + span_err!(diagnostic, meta.span, E0551, "incorrect meta item"); + } - false - } - }; + false + } + }; - let mut since = None; - let mut note = None; - for meta in metas { - match &meta.node { - NestedMetaItemKind::MetaItem(mi) => { - match &*mi.name().as_str() { - "since" => if !get(mi, &mut since) { continue 'outer }, - "note" => if !get(mi, &mut note) { continue 'outer }, - _ => { - handle_errors( - sess, - meta.span, - AttrError::UnknownMetaItem(mi.name(), &["since", "note"]), - ); - continue 'outer + let mut since = None; + let mut note = None; + for meta in list { + match &meta.node { + NestedMetaItemKind::MetaItem(mi) => { + match &*mi.name().as_str() { + "since" => if !get(mi, &mut since) { continue 'outer }, + "note" => if !get(mi, &mut note) { continue 'outer }, + _ => { + handle_errors( + sess, + meta.span, + AttrError::UnknownMetaItem(mi.name(), &["since", "note"]), + ); + continue 'outer + } } } - } - NestedMetaItemKind::Literal(lit) => { - handle_errors( - sess, - lit.span, - AttrError::UnsupportedLiteral( - "item in `deprecated` must be a key/value pair", - false, - ), - ); - continue 'outer + NestedMetaItemKind::Literal(lit) => { + handle_errors( + sess, + lit.span, + AttrError::UnsupportedLiteral( + "item in `deprecated` must be a key/value pair", + false, + ), + ); + continue 'outer + } } } - } - Some(Deprecation {since: since, note: note}) - } else { - Some(Deprecation{since: None, note: None}) - } + Some(Deprecation { since, note }) + } + }; } depr diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 58be7c3e085c3..7e0342e1cba55 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -161,6 +161,10 @@ fn name_from_path(path: &Path) -> Name { } impl Attribute { + /// Returns `true` if the attribute's path matches the argument. If it matches, then the + /// attribute is marked as used. + /// + /// To check the attribute name without marking it used, use the `path` field directly. pub fn check_name(&self, name: &str) -> bool { let matches = self.path == name; if matches { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9dd17b420aa44..9a63a2c678b88 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1176,9 +1176,15 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu ("stable", Whitelisted, template!(List: r#"feature = "name", since = "version""#), Ungated), ("unstable", Whitelisted, template!(List: r#"feature = "name", reason = "...", issue = "N""#), Ungated), - ("deprecated", Normal, template!(Word, List: r#"/*opt*/ since = "version", - /*opt*/ note = "reason"#, - NameValueStr: "reason"), Ungated), + ("deprecated", + Normal, + template!( + Word, + List: r#"/*opt*/ since = "version", /*opt*/ note = "reason"#, + NameValueStr: "reason" + ), + Ungated + ), ("rustc_paren_sugar", Normal, template!(Word), Gated(Stability::Unstable, "unboxed_closures", diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index ca3f380ed2825..ecb74719d74cc 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -26,3 +26,8 @@ pub struct V; // 'Deprecated$' #[deprecated] pub struct W; + +// @matches deprecated/struct.X.html '//*[@class="stab deprecated"]' \ +// 'Deprecated: shorthand reason$' +#[deprecated = "shorthand reason"] +pub struct X; diff --git a/src/test/ui/deprecation/deprecation-sanity.rs b/src/test/ui/deprecation/deprecation-sanity.rs index 09bae0bdfb13e..a559908b792bb 100644 --- a/src/test/ui/deprecation/deprecation-sanity.rs +++ b/src/test/ui/deprecation/deprecation-sanity.rs @@ -15,6 +15,12 @@ mod bogus_attribute_types_1 { #[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item fn f6() { } + + #[deprecated(note = b"test")] //~ ERROR literal in `deprecated` value must be a string + fn f7() { } + + #[deprecated("test")] //~ ERROR item in `deprecated` must be a key/value pair + fn f8() { } } #[deprecated(since = "a", note = "b")] diff --git a/src/test/ui/deprecation/deprecation-sanity.stderr b/src/test/ui/deprecation/deprecation-sanity.stderr index a8bfcc23cc8cc..a071a4fc10d51 100644 --- a/src/test/ui/deprecation/deprecation-sanity.stderr +++ b/src/test/ui/deprecation/deprecation-sanity.stderr @@ -28,19 +28,31 @@ error[E0551]: incorrect meta item LL | #[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item | ^^^^^^^^ +error[E0565]: literal in `deprecated` value must be a string + --> $DIR/deprecation-sanity.rs:19:25 + | +LL | #[deprecated(note = b"test")] //~ ERROR literal in `deprecated` value must be a string + | ^^^^^^^ help: consider removing the prefix: `"test"` + +error[E0565]: item in `deprecated` must be a key/value pair + --> $DIR/deprecation-sanity.rs:22:18 + | +LL | #[deprecated("test")] //~ ERROR item in `deprecated` must be a key/value pair + | ^^^^^^ + error[E0550]: multiple deprecated attributes - --> $DIR/deprecation-sanity.rs:22:1 + --> $DIR/deprecation-sanity.rs:28:1 | LL | fn multiple1() { } //~ ERROR multiple deprecated attributes | ^^^^^^^^^^^^^^^^^^ error[E0538]: multiple 'since' items - --> $DIR/deprecation-sanity.rs:24:27 + --> $DIR/deprecation-sanity.rs:30:27 | LL | #[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items | ^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -Some errors occurred: E0538, E0541, E0550, E0551. +Some errors occurred: E0538, E0541, E0550, E0551, E0565. For more information about an error, try `rustc --explain E0538`. diff --git a/src/test/ui/deprecation/invalid-literal.rs b/src/test/ui/deprecation/invalid-literal.rs new file mode 100644 index 0000000000000..7e0d8cdfc2f72 --- /dev/null +++ b/src/test/ui/deprecation/invalid-literal.rs @@ -0,0 +1,4 @@ +#[deprecated = b"test"] //~ ERROR attribute must be of the form +fn foo() {} + +fn main() {} diff --git a/src/test/ui/deprecation/invalid-literal.stderr b/src/test/ui/deprecation/invalid-literal.stderr new file mode 100644 index 0000000000000..f13d599c0b137 --- /dev/null +++ b/src/test/ui/deprecation/invalid-literal.stderr @@ -0,0 +1,8 @@ +error: attribute must be of the form `#[deprecated]` or `#[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason)]` or `#[deprecated = "reason"]` + --> $DIR/invalid-literal.rs:1:1 + | +LL | #[deprecated = b"test"] //~ ERROR attribute must be of the form + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +