allow shorthand syntax for deprecation reason

This commit is contained in:
Andy Russell 2019-02-04 12:41:01 -05:00
parent d30b99f9c2
commit 113b7f7be1
No known key found for this signature in database
GPG Key ID: BE2221033EDBC374
8 changed files with 117 additions and 67 deletions

View File

@ -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<Symbol>| {
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<Symbol>| {
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

View File

@ -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 {

View File

@ -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",

View File

@ -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;

View File

@ -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")]

View File

@ -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`.

View File

@ -0,0 +1,4 @@
#[deprecated = b"test"] //~ ERROR attribute must be of the form
fn foo() {}
fn main() {}

View File

@ -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