//! Parsing and validation of builtin attributes
-use ast::{self, Attribute, MetaItem, Name, NestedMetaItemKind};
+use crate::ast::{self, Attribute, MetaItem, Name, NestedMetaItemKind};
+use crate::feature_gate::{Features, GatedCfg};
+use crate::parse::ParseSess;
+
use errors::{Applicability, Handler};
-use feature_gate::{Features, GatedCfg};
-use parse::ParseSess;
use syntax_pos::{symbol::Symbol, Span};
use super::{list_contains_name, mark_used, MetaItemKind};
let mut err = struct_span_err!(diag, span, E0565, "{}", msg);
if is_bytestr {
if let Ok(lint_str) = sess.source_map().span_to_snippet(span) {
- err.span_suggestion_with_applicability(
+ err.span_suggestion(
span,
"consider removing the prefix",
format!("{}", &lint_str[1..]),
Never,
}
+#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)]
+pub enum OptimizeAttr {
+ None,
+ Speed,
+ Size,
+}
+
#[derive(Copy, Clone, PartialEq)]
pub enum UnwindAttr {
Allowed,
pub struct RustcDeprecation {
pub since: Symbol,
pub reason: Symbol,
+ /// A text snippet used to completely replace any use of the deprecated item in an expression.
+ pub suggestion: Option<Symbol>,
}
-/// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
+/// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`.
/// This will not perform any "sanity checks" on the form of the attributes.
pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
attrs.iter().any(|item| {
})
}
-/// Find the first stability attribute. `None` if none exists.
+/// Finds the first stability attribute. `None` if none exists.
pub fn find_stability(sess: &ParseSess, attrs: &[Attribute],
item_sp: Span) -> Option<Stability> {
find_stability_generic(sess, attrs.iter(), item_sp)
-> Option<Stability>
where I: Iterator<Item = &'a Attribute>
{
- use self::StabilityLevel::*;
+ use StabilityLevel::*;
let mut stab: Option<Stability> = None;
let mut rustc_depr: Option<RustcDeprecation> = None;
continue 'outer
}
- get_meta!(since, reason);
+ get_meta!(since, reason, suggestion);
match (since, reason) {
(Some(since), Some(reason)) => {
rustc_depr = Some(RustcDeprecation {
since,
reason,
+ suggestion,
})
}
(None, _) => {
pub note: Option<Symbol>,
}
-/// Find the deprecation attribute. `None` if none exists.
+/// Finds the deprecation attribute. `None` if none exists.
pub fn find_deprecation(sess: &ParseSess, attrs: &[Attribute],
item_sp: Span) -> Option<Deprecation> {
find_deprecation_generic(sess, attrs.iter(), item_sp)
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
impl IntType {
#[inline]
pub fn is_signed(self) -> bool {
- use self::IntType::*;
+ use IntType::*;
match self {
SignedInt(..) => true,
/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
/// concerns to the only non-ZST field.
pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
- use self::ReprAttr::*;
+ use ReprAttr::*;
let mut acc = Vec::new();
let diagnostic = &sess.span_diagnostic;
"incorrect `repr(align)` attribute format");
match value.node {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
- err.span_suggestion_with_applicability(
+ err.span_suggestion(
item.span,
"use parentheses instead",
format!("align({})", int),
);
}
ast::LitKind::Str(s, _) => {
- err.span_suggestion_with_applicability(
+ err.span_suggestion(
item.span,
"use parentheses instead",
format!("align({})", s),
}
fn int_type_of_word(s: &str) -> Option<IntType> {
- use self::IntType::*;
+ use IntType::*;
match s {
"i8" => Some(SignedInt(ast::IntTy::I8)),