Skip to content

Commit

Permalink
allow shorthand syntax for deprecation reason
Browse files Browse the repository at this point in the history
  • Loading branch information
euclio committed Feb 5, 2019
1 parent d30b99f commit 113b7f7
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 67 deletions.
125 changes: 65 additions & 60 deletions src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
12 changes: 9 additions & 3 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 5 additions & 0 deletions src/test/rustdoc/deprecated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
6 changes: 6 additions & 0 deletions src/test/ui/deprecation/deprecation-sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
20 changes: 16 additions & 4 deletions src/test/ui/deprecation/deprecation-sanity.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
4 changes: 4 additions & 0 deletions src/test/ui/deprecation/invalid-literal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[deprecated = b"test"] //~ ERROR attribute must be of the form
fn foo() {}

fn main() {}
8 changes: 8 additions & 0 deletions src/test/ui/deprecation/invalid-literal.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 113b7f7

Please sign in to comment.