diff options
Diffstat (limited to 'src/libsyntax/attr/builtin.rs')
| -rw-r--r-- | src/libsyntax/attr/builtin.rs | 202 | 
1 files changed, 147 insertions, 55 deletions
| diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 1cc2e62a9c6..1bbc1accc07 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -24,10 +24,11 @@ enum AttrError { MissingSince, MissingFeature, MultipleStabilityLevels, - UnsupportedLiteral + UnsupportedLiteral(&'static str, /* is_bytestr */ bool), } -fn handle_errors(diag: &Handler, span: Span, error: AttrError) { +fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { + let diag = &sess.span_diagnostic; match error { AttrError::MultipleItem(item) => span_err!(diag, span, E0538, "multiple '{}' items", item), @@ -44,7 +45,23 @@ fn handle_errors(diag: &Handler, span: Span, error: AttrError) { AttrError::MissingFeature => span_err!(diag, span, E0546, "missing 'feature'"), AttrError::MultipleStabilityLevels => span_err!(diag, span, E0544, "multiple stability levels"), - AttrError::UnsupportedLiteral => span_err!(diag, span, E0565, "unsupported literal"), + AttrError::UnsupportedLiteral( + msg, + is_bytestr, + ) => { + 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( + span, + "consider removing the prefix", + format!("{}", &lint_str[1..]), + Applicability::MaybeIncorrect, + ); + } + } + err.emit(); + } } } @@ -161,12 +178,12 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { } /// Find the first stability attribute. `None` if none exists. -pub fn find_stability(diagnostic: &Handler, attrs: &[Attribute], +pub fn find_stability(sess: &ParseSess, attrs: &[Attribute], item_sp: Span) -> Option<Stability> { - find_stability_generic(diagnostic, attrs.iter(), item_sp) + find_stability_generic(sess, attrs.iter(), item_sp) } -fn find_stability_generic<'a, I>(diagnostic: &Handler, +fn find_stability_generic<'a, I>(sess: &ParseSess, attrs_iter: I, item_sp: Span) -> Option<Stability> @@ -178,6 +195,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut rustc_depr: Option<RustcDeprecation> = None; let mut rustc_const_unstable: Option<Symbol> = None; let mut promotable = false; + let diagnostic = &sess.span_diagnostic; 'outer: for attr in attrs_iter { if ![ @@ -202,7 +220,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option<Symbol>| { if item.is_some() { - handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); return false } if let Some(v) = meta.value_str() { @@ -229,14 +247,22 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, _ => { let expected = &[ $( stringify!($name) ),+ ]; handle_errors( - diagnostic, + sess, mi.span, - AttrError::UnknownMetaItem(mi.name(), expected)); + AttrError::UnknownMetaItem(mi.name(), expected), + ); continue 'outer } } } else { - handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral); + handle_errors( + sess, + meta.span, + AttrError::UnsupportedLiteral( + "unsupported literal", + false, + ), + ); continue 'outer } } @@ -261,7 +287,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, }) } (None, _) => { - handle_errors(diagnostic, attr.span(), AttrError::MissingSince); + handle_errors(sess, attr.span(), AttrError::MissingSince); continue } _ => { @@ -287,7 +313,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } "unstable" => { if stab.is_some() { - handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels); + handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels); break } @@ -302,7 +328,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, "issue" => if !get(mi, &mut issue) { continue 'outer }, _ => { handle_errors( - diagnostic, + sess, meta.span, AttrError::UnknownMetaItem( mi.name(), @@ -313,7 +339,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } } } else { - handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral); + handle_errors( + sess, + meta.span, + AttrError::UnsupportedLiteral( + "unsupported literal", + false, + ), + ); continue 'outer } } @@ -340,7 +373,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, }) } (None, _, _) => { - handle_errors(diagnostic, attr.span(), AttrError::MissingFeature); + handle_errors(sess, attr.span(), AttrError::MissingFeature); continue } _ => { @@ -351,29 +384,41 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } "stable" => { if stab.is_some() { - handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels); + handle_errors(sess, attr.span(), AttrError::MultipleStabilityLevels); break } let mut feature = None; let mut since = None; for meta in metas { - if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name().as_str() { - "feature" => if !get(mi, &mut feature) { continue 'outer }, - "since" => if !get(mi, &mut since) { continue 'outer }, - _ => { - handle_errors( - diagnostic, - meta.span, - AttrError::UnknownMetaItem(mi.name(), &["since", "note"]), - ); - continue 'outer + match &meta.node { + NestedMetaItemKind::MetaItem(mi) => { + match &*mi.name().as_str() { + "feature" => if !get(mi, &mut feature) { continue 'outer }, + "since" => if !get(mi, &mut since) { 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( + "unsupported literal", + false, + ), + ); + continue 'outer } - } else { - handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral); - continue 'outer } } @@ -390,11 +435,11 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, }) } (None, _) => { - handle_errors(diagnostic, attr.span(), AttrError::MissingFeature); + handle_errors(sess, attr.span(), AttrError::MissingFeature); continue } _ => { - handle_errors(diagnostic, attr.span(), AttrError::MissingSince); + handle_errors(sess, attr.span(), AttrError::MissingSince); continue } } @@ -462,7 +507,15 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat error(cfg.span, "unexpected parentheses after `cfg` predicate key") } MetaItemKind::NameValue(lit) if !lit.node.is_str() => { - error(lit.span, "literal in `cfg` predicate value must be a string") + handle_errors( + sess, + lit.span, + AttrError::UnsupportedLiteral( + "literal in `cfg` predicate value must be a string", + lit.node.is_bytestr() + ), + ); + true } MetaItemKind::NameValue(..) | MetaItemKind::Word => { sess.config.contains(&(cfg.name(), cfg.value_str())) @@ -481,7 +534,14 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) ast::MetaItemKind::List(ref mis) => { for mi in mis.iter() { if !mi.is_meta_item() { - handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral); + handle_errors( + sess, + mi.span, + AttrError::UnsupportedLiteral( + "unsupported literal", + false + ), + ); return false; } } @@ -523,18 +583,19 @@ pub struct Deprecation { } /// Find the deprecation attribute. `None` if none exists. -pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute], +pub fn find_deprecation(sess: &ParseSess, attrs: &[Attribute], item_sp: Span) -> Option<Deprecation> { - find_deprecation_generic(diagnostic, attrs.iter(), item_sp) + find_deprecation_generic(sess, attrs.iter(), item_sp) } -fn find_deprecation_generic<'a, I>(diagnostic: &Handler, +fn find_deprecation_generic<'a, I>(sess: &ParseSess, attrs_iter: I, item_sp: Span) -> Option<Deprecation> where I: Iterator<Item = &'a Attribute> { let mut depr: Option<Deprecation> = None; + let diagnostic = &sess.span_diagnostic; 'outer: for attr in attrs_iter { if attr.path != "deprecated" { @@ -551,14 +612,27 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, depr = if let Some(metas) = attr.meta_item_list() { let get = |meta: &MetaItem, item: &mut Option<Symbol>| { if item.is_some() { - handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); + handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); return false } if let Some(v) = meta.value_str() { *item = Some(v); true } else { - span_err!(diagnostic, meta.span, E0551, "incorrect meta item"); + 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 } }; @@ -566,22 +640,32 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, let mut since = None; let mut note = None; for meta in metas { - if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name().as_str() { - "since" => if !get(mi, &mut since) { continue 'outer }, - "note" => if !get(mi, &mut note) { continue 'outer }, - _ => { - handle_errors( - diagnostic, - meta.span, - AttrError::UnknownMetaItem(mi.name(), &["since", "note"]), - ); - continue 'outer + 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 + } } } - } else { - handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral); - continue 'outer + NestedMetaItemKind::Literal(lit) => { + handle_errors( + sess, + lit.span, + AttrError::UnsupportedLiteral( + "item in `deprecated` must be a key/value pair", + false, + ), + ); + continue 'outer + } } } @@ -629,16 +713,24 @@ impl IntType { /// the same discriminant size that the corresponding C enum would or C /// structure layout, `packed` to remove padding, and `transparent` to elegate representation /// concerns to the only non-ZST field. -pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> { +pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> { use self::ReprAttr::*; let mut acc = Vec::new(); + let diagnostic = &sess.span_diagnostic; if attr.path == "repr" { if let Some(items) = attr.meta_item_list() { mark_used(attr); for item in items { if !item.is_meta_item() { - handle_errors(diagnostic, item.span, AttrError::UnsupportedLiteral); + handle_errors( + sess, + item.span, + AttrError::UnsupportedLiteral( + "meta item in `repr` must be an identifier", + false, + ), + ); continue } | 
