Auto merge of #36066 - jseyfried:rollup, r=Manishearth
Batch up libsyntax breaking changes Batch of the following syntax-[breaking-change] changes: - #35591: Add a field `span: Span` to `ast::Generics`. - #35618: Remove variant `Mod` of `ast::PathListItemKind` and refactor the remaining variant `ast::PathListKind::Ident` to a struct `ast::PathListKind_`. - #35480: Change uses of `Constness` in the AST to `Spanned<Constness>`. - c.f. `MethodSig`, `ItemKind` - #35728: Refactor `cx.pat_enum()` into `cx.pat_tuple_struct()` and `cx.pat_path()`. - #35850: Generalize the elements of lists in attributes from `MetaItem` to a new type `NestedMetaItem` that can represent a `MetaItem` or a literal. - #35917: Remove traits `AttrMetaMethods`, `AttributeMethods`, and `AttrNestedMetaItemMethods`. - Besides removing imports of these traits, this won't cause fallout. - Add a variant `Union` to `ItemKind` to future proof for `union` (c.f. #36016). - Remove inherent methods `attrs` and `fold_attrs` of `Annotatable`. - Use methods `attrs` and `map_attrs` of `HasAttrs` instead. r? @Manishearth
This commit is contained in:
commit
71ee82a8aa
104 changed files with 1301 additions and 859 deletions
|
|
@ -11,7 +11,6 @@
|
|||
use session::Session;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
|
||||
|
|
@ -52,18 +51,22 @@ impl<'a> CheckAttrVisitor<'a> {
|
|||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for word in words {
|
||||
let word: &str = &word.name();
|
||||
let message = match word {
|
||||
let name = match word.name() {
|
||||
Some(word) => word,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let message = match &*name {
|
||||
"C" => {
|
||||
if target != Target::Struct && target != Target::Enum {
|
||||
"attribute should be applied to struct or enum"
|
||||
"attribute should be applied to struct or enum"
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
"packed" |
|
||||
"simd" => {
|
||||
"packed" | "simd" => {
|
||||
if target != Target::Struct {
|
||||
"attribute should be applied to struct"
|
||||
} else {
|
||||
|
|
@ -74,13 +77,14 @@ impl<'a> CheckAttrVisitor<'a> {
|
|||
"i32" | "u32" | "i64" | "u64" |
|
||||
"isize" | "usize" => {
|
||||
if target != Target::Enum {
|
||||
"attribute should be applied to enum"
|
||||
"attribute should be applied to enum"
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
span_err!(self.sess, attr.span, E0517, "{}", message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
//! and returns a piece of the same type.
|
||||
|
||||
use hir::*;
|
||||
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
|
||||
use syntax::ast::MetaItemKind;
|
||||
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_};
|
||||
use syntax::ast::{NestedMetaItem, NestedMetaItemKind, MetaItem, MetaItemKind};
|
||||
use hir;
|
||||
use syntax_pos::Span;
|
||||
use syntax::codemap::{respan, Spanned};
|
||||
|
|
@ -38,6 +38,10 @@ pub trait Folder : Sized {
|
|||
noop_fold_meta_items(meta_items, self)
|
||||
}
|
||||
|
||||
fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
|
||||
noop_fold_meta_list_item(list_item, self)
|
||||
}
|
||||
|
||||
fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
|
||||
noop_fold_meta_item(meta_item, self)
|
||||
}
|
||||
|
|
@ -271,16 +275,10 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
|
|||
ViewPathList(fld.fold_path(path),
|
||||
path_list_idents.move_map(|path_list_ident| {
|
||||
Spanned {
|
||||
node: match path_list_ident.node {
|
||||
PathListIdent { id, name, rename } => PathListIdent {
|
||||
id: fld.new_id(id),
|
||||
name: name,
|
||||
rename: rename,
|
||||
},
|
||||
PathListMod { id, rename } => PathListMod {
|
||||
id: fld.new_id(id),
|
||||
rename: rename,
|
||||
},
|
||||
node: PathListItem_ {
|
||||
id: fld.new_id(path_list_ident.node.id),
|
||||
name: path_list_ident.node.name,
|
||||
rename: path_list_ident.node.rename,
|
||||
},
|
||||
span: fld.new_span(path_list_ident.span),
|
||||
}
|
||||
|
|
@ -486,13 +484,26 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attr
|
|||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_meta_list_item<T: Folder>(li: NestedMetaItem, fld: &mut T)
|
||||
-> NestedMetaItem {
|
||||
Spanned {
|
||||
node: match li.node {
|
||||
NestedMetaItemKind::MetaItem(mi) => {
|
||||
NestedMetaItemKind::MetaItem(fld.fold_meta_item(mi))
|
||||
},
|
||||
NestedMetaItemKind::Literal(lit) => NestedMetaItemKind::Literal(lit)
|
||||
},
|
||||
span: fld.new_span(li.span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
|
||||
mi.map(|Spanned { node, span }| {
|
||||
Spanned {
|
||||
node: match node {
|
||||
MetaItemKind::Word(id) => MetaItemKind::Word(id),
|
||||
MetaItemKind::List(id, mis) => {
|
||||
MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_item(e)))
|
||||
MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_list_item(e)))
|
||||
}
|
||||
MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s),
|
||||
},
|
||||
|
|
@ -577,13 +588,14 @@ pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T) ->
|
|||
o_lt.map(|lt| fld.fold_lifetime(lt))
|
||||
}
|
||||
|
||||
pub fn noop_fold_generics<T: Folder>(Generics { ty_params, lifetimes, where_clause }: Generics,
|
||||
pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause, span}: Generics,
|
||||
fld: &mut T)
|
||||
-> Generics {
|
||||
Generics {
|
||||
ty_params: fld.fold_ty_params(ty_params),
|
||||
lifetimes: fld.fold_lifetime_defs(lifetimes),
|
||||
where_clause: fld.fold_where_clause(where_clause),
|
||||
span: fld.new_span(span),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -444,12 +444,12 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
_prefix: &'v Path,
|
||||
item: &'v PathListItem) {
|
||||
visitor.visit_id(item.node.id());
|
||||
walk_opt_name(visitor, item.span, item.node.name());
|
||||
walk_opt_name(visitor, item.span, item.node.rename());
|
||||
pub fn walk_path_list_item<'v, V>(visitor: &mut V, _prefix: &'v Path, item: &'v PathListItem)
|
||||
where V: Visitor<'v>,
|
||||
{
|
||||
visitor.visit_id(item.node.id);
|
||||
visitor.visit_name(item.span, item.node.name);
|
||||
walk_opt_name(visitor, item.span, item.node.rename);
|
||||
}
|
||||
|
||||
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
|
|
|
|||
|
|
@ -218,16 +218,10 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem {
|
||||
Spanned {
|
||||
node: match path_list_ident.node {
|
||||
PathListItemKind::Ident { id, name, rename } => hir::PathListIdent {
|
||||
id: id,
|
||||
name: name.name,
|
||||
rename: rename.map(|x| x.name),
|
||||
},
|
||||
PathListItemKind::Mod { id, rename } => hir::PathListMod {
|
||||
id: id,
|
||||
rename: rename.map(|x| x.name),
|
||||
},
|
||||
node: hir::PathListItem_ {
|
||||
id: path_list_ident.node.id,
|
||||
name: path_list_ident.node.name.name,
|
||||
rename: path_list_ident.node.rename.map(|rename| rename.name),
|
||||
},
|
||||
span: path_list_ident.span,
|
||||
}
|
||||
|
|
@ -466,6 +460,7 @@ impl<'a> LoweringContext<'a> {
|
|||
ty_params: self.lower_ty_params(&g.ty_params),
|
||||
lifetimes: self.lower_lifetime_defs(&g.lifetimes),
|
||||
where_clause: self.lower_where_clause(&g.where_clause),
|
||||
span: g.span,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -643,6 +638,7 @@ impl<'a> LoweringContext<'a> {
|
|||
let struct_def = self.lower_variant_data(struct_def);
|
||||
hir::ItemStruct(struct_def, self.lower_generics(generics))
|
||||
}
|
||||
ItemKind::Union(..) => panic!("`union` is not yet implemented"),
|
||||
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
||||
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
|
||||
self.lower_trait_ref(trait_ref))
|
||||
|
|
@ -809,8 +805,8 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_constness(&mut self, c: Constness) -> hir::Constness {
|
||||
match c {
|
||||
fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
|
||||
match c.node {
|
||||
Constness::Const => hir::Constness::Const,
|
||||
Constness::NotConst => hir::Constness::NotConst,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@
|
|||
|
||||
pub use self::Code::*;
|
||||
|
||||
use hir::map::{self, Node};
|
||||
use syntax::abi;
|
||||
use hir::{Block, FnDecl};
|
||||
use syntax::ast::{Attribute, Name, NodeId};
|
||||
use hir as ast;
|
||||
use syntax_pos::Span;
|
||||
use hir::map::{self, Node};
|
||||
use hir::{Block, FnDecl};
|
||||
use hir::intravisit::FnKind;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{Attribute, Name, NodeId};
|
||||
use syntax_pos::Span;
|
||||
|
||||
/// An FnLikeNode is a Node that is like a fn, in that it has a decl
|
||||
/// and a body (as well as a NodeId, a span, etc).
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
|||
match view_path.node {
|
||||
ViewPathList(_, ref paths) => {
|
||||
for path in paths {
|
||||
this.insert(path.node.id(), NodeItem(i));
|
||||
this.insert(path.node.id, NodeItem(i));
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
|
|||
let def_data = match i.node {
|
||||
ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
|
||||
DefPathData::Impl,
|
||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
|
||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
|
||||
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
|
||||
DefPathData::TypeNs(i.ident.name.as_str()),
|
||||
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
|
||||
|
|
@ -164,7 +164,7 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
|
|||
});
|
||||
}
|
||||
}
|
||||
ItemKind::Struct(ref struct_def, _) => {
|
||||
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
|
||||
// If this is a tuple-like struct, register the constructor.
|
||||
if !struct_def.is_struct() {
|
||||
this.create_def(struct_def.id(),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ pub use self::FunctionRetTy::*;
|
|||
pub use self::ForeignItem_::*;
|
||||
pub use self::Item_::*;
|
||||
pub use self::Mutability::*;
|
||||
pub use self::PathListItem_::*;
|
||||
pub use self::PrimTy::*;
|
||||
pub use self::Stmt_::*;
|
||||
pub use self::TraitItem_::*;
|
||||
|
|
@ -36,7 +35,7 @@ use hir::def::Def;
|
|||
use hir::def_id::DefId;
|
||||
use util::nodemap::{NodeMap, FnvHashSet};
|
||||
|
||||
use syntax_pos::{BytePos, mk_sp, Span, ExpnId};
|
||||
use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP};
|
||||
use syntax::codemap::{self, respan, Spanned};
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||
|
|
@ -301,6 +300,7 @@ pub struct Generics {
|
|||
pub lifetimes: HirVec<LifetimeDef>,
|
||||
pub ty_params: HirVec<TyParam>,
|
||||
pub where_clause: WhereClause,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
|
|
@ -312,6 +312,7 @@ impl Generics {
|
|||
id: DUMMY_NODE_ID,
|
||||
predicates: HirVec::new(),
|
||||
},
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -326,38 +327,6 @@ impl Generics {
|
|||
pub fn is_parameterized(&self) -> bool {
|
||||
self.is_lt_parameterized() || self.is_type_parameterized()
|
||||
}
|
||||
|
||||
// Does return a span which includes lifetimes and type parameters,
|
||||
// not where clause.
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
if !self.is_parameterized() {
|
||||
None
|
||||
} else {
|
||||
let mut span: Option<Span> = None;
|
||||
for lifetime in self.lifetimes.iter() {
|
||||
if let Some(ref mut span) = span {
|
||||
let life_span = lifetime.lifetime.span;
|
||||
span.hi = if span.hi > life_span.hi { span.hi } else { life_span.hi };
|
||||
span.lo = if span.lo < life_span.lo { span.lo } else { life_span.lo };
|
||||
} else {
|
||||
span = Some(lifetime.lifetime.span.clone());
|
||||
}
|
||||
}
|
||||
for ty_param in self.ty_params.iter() {
|
||||
if let Some(ref mut span) = span {
|
||||
span.lo = if span.lo < ty_param.span.lo { span.lo } else { ty_param.span.lo };
|
||||
span.hi = if span.hi > ty_param.span.hi { span.hi } else { ty_param.span.hi };
|
||||
} else {
|
||||
span = Some(ty_param.span.clone());
|
||||
}
|
||||
}
|
||||
if let Some(ref mut span) = span {
|
||||
span.lo = span.lo - BytePos(1);
|
||||
span.hi = span.hi + BytePos(1);
|
||||
}
|
||||
span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `where` clause in a definition
|
||||
|
|
@ -1337,39 +1306,11 @@ pub struct Variant_ {
|
|||
pub type Variant = Spanned<Variant_>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
pub enum PathListItem_ {
|
||||
PathListIdent {
|
||||
name: Name,
|
||||
/// renamed in list, eg `use foo::{bar as baz};`
|
||||
rename: Option<Name>,
|
||||
id: NodeId,
|
||||
},
|
||||
PathListMod {
|
||||
/// renamed in list, eg `use foo::{self as baz};`
|
||||
rename: Option<Name>,
|
||||
id: NodeId,
|
||||
},
|
||||
}
|
||||
|
||||
impl PathListItem_ {
|
||||
pub fn id(&self) -> NodeId {
|
||||
match *self {
|
||||
PathListIdent { id, .. } | PathListMod { id, .. } => id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<Name> {
|
||||
match *self {
|
||||
PathListIdent { name, .. } => Some(name),
|
||||
PathListMod { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename(&self) -> Option<Name> {
|
||||
match *self {
|
||||
PathListIdent { rename, .. } | PathListMod { rename, .. } => rename,
|
||||
}
|
||||
}
|
||||
pub struct PathListItem_ {
|
||||
pub name: Name,
|
||||
/// renamed in list, eg `use foo::{bar as baz};`
|
||||
pub rename: Option<Name>,
|
||||
pub id: NodeId,
|
||||
}
|
||||
|
||||
pub type PathListItem = Spanned<PathListItem_>;
|
||||
|
|
|
|||
|
|
@ -523,6 +523,7 @@ impl<'a> State<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: hir::HirVec::new(),
|
||||
},
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
|
||||
}
|
||||
|
|
@ -2133,16 +2134,7 @@ impl<'a> State<'a> {
|
|||
self.print_path(path, false, 0)?;
|
||||
word(&mut self.s, "::{")?;
|
||||
}
|
||||
self.commasep(Inconsistent, &segments[..], |s, w| {
|
||||
match w.node {
|
||||
hir::PathListIdent { name, .. } => {
|
||||
s.print_name(name)
|
||||
}
|
||||
hir::PathListMod { .. } => {
|
||||
word(&mut s.s, "self")
|
||||
}
|
||||
}
|
||||
})?;
|
||||
self.commasep(Inconsistent, &segments[..], |s, w| s.print_name(w.node.name))?;
|
||||
word(&mut self.s, "}")
|
||||
}
|
||||
}
|
||||
|
|
@ -2224,6 +2216,7 @@ impl<'a> State<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: hir::HirVec::new(),
|
||||
},
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
self.print_fn(decl,
|
||||
unsafety,
|
||||
|
|
|
|||
|
|
@ -1030,7 +1030,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
= node_inner.expect("expect item fn");
|
||||
let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver);
|
||||
let (fn_decl, generics) = rebuilder.rebuild();
|
||||
self.give_expl_lifetime_param(err, &fn_decl, unsafety, constness, name, &generics, span);
|
||||
self.give_expl_lifetime_param(
|
||||
err, &fn_decl, unsafety, constness, name, &generics, span);
|
||||
}
|
||||
|
||||
pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) {
|
||||
|
|
@ -1297,6 +1298,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
|
|||
lifetimes: lifetimes.into(),
|
||||
ty_params: ty_params,
|
||||
where_clause: where_clause,
|
||||
span: generics.span,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use util::nodemap::FnvHashMap;
|
|||
use std::cmp;
|
||||
use std::default::Default as StdDefault;
|
||||
use std::mem;
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
|
@ -372,12 +372,10 @@ pub fn gather_attr(attr: &ast::Attribute)
|
|||
return out;
|
||||
};
|
||||
|
||||
for meta in metas {
|
||||
out.push(if meta.is_word() {
|
||||
Ok((meta.name().clone(), level, meta.span))
|
||||
} else {
|
||||
Err(meta.span)
|
||||
});
|
||||
for li in metas {
|
||||
out.push(li.word().map_or(Err(li.span), |word| {
|
||||
Ok((word.name().clone(), level, word.span))
|
||||
}));
|
||||
}
|
||||
|
||||
out
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) {
|
||||
self.lookup_and_handle_definition(item.node.id());
|
||||
self.lookup_and_handle_definition(item.node.id);
|
||||
intravisit::walk_path_list_item(self, path, item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ use middle::weak_lang_items;
|
|||
use util::nodemap::FnvHashMap;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse::token::InternedString;
|
||||
use hir::intravisit::Visitor;
|
||||
use hir;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
use session::Session;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
|
||||
for attr in &krate.attrs {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
use syntax::ast;
|
||||
use syntax::ast::{NodeId, Attribute};
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};
|
||||
use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
|
||||
use syntax::attr::{self, Stability, Deprecation};
|
||||
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||
|
||||
use hir;
|
||||
|
|
@ -631,7 +631,7 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
cb: &mut FnMut(DefId, Span,
|
||||
&Option<&Stability>,
|
||||
&Option<DeprecationEntry>)) {
|
||||
match tcx.expect_def(item.node.id()) {
|
||||
match tcx.expect_def(item.node.id) {
|
||||
Def::PrimTy(..) => {}
|
||||
def => {
|
||||
maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ use middle::cstore;
|
|||
|
||||
use syntax::ast::{self, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
|
|
@ -1773,8 +1772,9 @@ mod tests {
|
|||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use super::{OutputType, OutputTypes, Externs, PanicStrategy};
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::{ast, attr};
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::codemap::dummy_spanned;
|
||||
|
||||
fn optgroups() -> Vec<OptGroup> {
|
||||
super::rustc_optgroups().into_iter()
|
||||
|
|
@ -1803,7 +1803,9 @@ mod tests {
|
|||
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
|
||||
let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore));
|
||||
let cfg = build_configuration(&sess, cfg);
|
||||
assert!((attr::contains_name(&cfg[..], "test")));
|
||||
assert!(attr::contains(&cfg, &dummy_spanned(ast::MetaItemKind::Word({
|
||||
InternedString::new("test")
|
||||
}))));
|
||||
}
|
||||
|
||||
// When the user supplies --test and --cfg test, don't implicitly add
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ use util::nodemap::{FnvHashMap, FnvHashSet};
|
|||
use std::cmp;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax::attr::{AttributeMethods, AttrMetaMethods};
|
||||
use syntax_pos::Span;
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use std::rc::Rc;
|
|||
use std::slice;
|
||||
use std::vec::IntoIter;
|
||||
use syntax::ast::{self, CrateNum, Name, NodeId};
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ use rustc::middle::mem_categorization as mc;
|
|||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
use borrowck::BorrowckCtxt;
|
||||
|
||||
use syntax::ast::{self, MetaItem};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
|
|
@ -43,8 +42,9 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<P<MetaItem
|
|||
if attr.check_name("rustc_mir") {
|
||||
let items = attr.meta_item_list();
|
||||
for item in items.iter().flat_map(|l| l.iter()) {
|
||||
if item.check_name(name) {
|
||||
return Some(item.clone())
|
||||
match item.meta_item() {
|
||||
Some(mi) if mi.check_name(name) => return Some(mi.clone()),
|
||||
_ => continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -126,8 +126,6 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
bd: BD) -> DataflowResults<BD>
|
||||
where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
|
||||
{
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
|
||||
if let Some(item) = has_rustc_mir_with(attrs, name) {
|
||||
if let Some(s) = item.value_str() {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ use std::mem;
|
|||
use std::rc::Rc;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ use std::fs;
|
|||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use syntax::{ast, diagnostics, visit};
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax::parse::{self, PResult, token};
|
||||
use syntax::util::node_count::NodeCounter;
|
||||
use syntax;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ use std::thread;
|
|||
use rustc::session::early_error;
|
||||
|
||||
use syntax::{ast, json};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
|
||||
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
|
||||
use syntax::parse::{self, PResult};
|
||||
|
|
@ -655,17 +654,19 @@ impl RustcDefaultCalls {
|
|||
if !allow_unstable_cfg && GatedCfg::gate(&*cfg).is_some() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if cfg.is_word() {
|
||||
println!("{}", cfg.name());
|
||||
} else if cfg.is_value_str() {
|
||||
if let Some(s) = cfg.value_str() {
|
||||
println!("{}=\"{}\"", cfg.name(), s);
|
||||
}
|
||||
} else if let Some(s) = cfg.value_str() {
|
||||
println!("{}=\"{}\"", cfg.name(), s);
|
||||
} else if cfg.is_meta_item_list() {
|
||||
// Right now there are not and should not be any
|
||||
// MetaItemKind::List items in the configuration returned by
|
||||
// `build_configuration`.
|
||||
panic!("MetaItemKind::List encountered in default cfg")
|
||||
panic!("Found an unexpected list in cfg attribute '{}'!", cfg.name())
|
||||
} else {
|
||||
// There also shouldn't be literals.
|
||||
panic!("Found an unexpected literal in cfg attribute '{}'!", cfg.name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ use std::env;
|
|||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -116,14 +115,18 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
|
|||
for attr in self.tcx.get_attrs(def_id).iter() {
|
||||
if attr.check_name(IF_THIS_CHANGED) {
|
||||
let mut id = None;
|
||||
for meta_item in attr.meta_item_list().unwrap_or_default() {
|
||||
if meta_item.is_word() && id.is_none() {
|
||||
id = Some(meta_item.name().clone());
|
||||
} else {
|
||||
// FIXME better-encapsulate meta_item (don't directly access `node`)
|
||||
span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
|
||||
for list_item in attr.meta_item_list().unwrap_or_default() {
|
||||
match list_item.word() {
|
||||
Some(word) if id.is_none() => {
|
||||
id = Some(word.name().clone())
|
||||
},
|
||||
_ => {
|
||||
// FIXME better-encapsulate meta_item (don't directly access `node`)
|
||||
span_bug!(list_item.span(), "unexpected list-item {:?}", list_item.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let id = id.unwrap_or(InternedString::new(ID));
|
||||
self.if_this_changed.entry(id)
|
||||
.or_insert(FnvHashSet())
|
||||
|
|
@ -131,16 +134,21 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
|
|||
} else if attr.check_name(THEN_THIS_WOULD_NEED) {
|
||||
let mut dep_node_interned = None;
|
||||
let mut id = None;
|
||||
for meta_item in attr.meta_item_list().unwrap_or_default() {
|
||||
if meta_item.is_word() && dep_node_interned.is_none() {
|
||||
dep_node_interned = Some(meta_item.name().clone());
|
||||
} else if meta_item.is_word() && id.is_none() {
|
||||
id = Some(meta_item.name().clone());
|
||||
} else {
|
||||
// FIXME better-encapsulate meta_item (don't directly access `node`)
|
||||
span_bug!(meta_item.span(), "unexpected meta-item {:?}", meta_item.node)
|
||||
for list_item in attr.meta_item_list().unwrap_or_default() {
|
||||
match list_item.word() {
|
||||
Some(word) if dep_node_interned.is_none() => {
|
||||
dep_node_interned = Some(word.name().clone());
|
||||
},
|
||||
Some(word) if id.is_none() => {
|
||||
id = Some(word.name().clone())
|
||||
},
|
||||
_ => {
|
||||
// FIXME better-encapsulate meta_item (don't directly access `node`)
|
||||
span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dep_node = match dep_node_interned {
|
||||
Some(ref n) => {
|
||||
match DepNode::from_label_string(&n[..], def_id) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
//! at the beginning.
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttributeMethods;
|
||||
use std::hash::{Hash, SipHasher, Hasher};
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ use rustc::hir;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::Visitor;
|
||||
use rustc_data_structures::fnv::FnvHashSet;
|
||||
use syntax::ast::{self, Attribute, MetaItem};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ast::{self, Attribute, NestedMetaItem};
|
||||
use syntax::parse::token::InternedString;
|
||||
use rustc::ty::TyCtxt;
|
||||
|
||||
|
|
@ -71,13 +70,17 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
|
||||
fn expect_associated_value(&self, item: &MetaItem) -> InternedString {
|
||||
fn expect_associated_value(&self, item: &NestedMetaItem) -> InternedString {
|
||||
if let Some(value) = item.value_str() {
|
||||
value
|
||||
} else {
|
||||
self.tcx.sess.span_fatal(
|
||||
item.span,
|
||||
&format!("associated value expected for `{}`", item.name()));
|
||||
let msg = if let Some(name) = item.name() {
|
||||
format!("associated value expected for `{}`", name)
|
||||
} else {
|
||||
"expected an associated value".to_string()
|
||||
};
|
||||
|
||||
self.tcx.sess.span_fatal(item.span, &msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use lint::{LateContext, LintContext, LintArray};
|
|||
use lint::{LintPass, LateLintPass};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir::{self, PatKind};
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ use lint::{LintPass, LateLintPass};
|
|||
use std::collections::HashSet;
|
||||
|
||||
use syntax::{ast};
|
||||
use syntax::attr::{self, AttrMetaMethods, AttributeMethods};
|
||||
use syntax_pos::Span;
|
||||
use syntax::attr;
|
||||
use syntax_pos::{Span};
|
||||
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::intravisit::FnKind;
|
||||
|
|
@ -317,7 +317,7 @@ impl LateLintPass for MissingDoc {
|
|||
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
|
||||
attr.check_name("doc") && match attr.meta_item_list() {
|
||||
None => false,
|
||||
Some(l) => attr::contains_name(&l[..], "hidden"),
|
||||
Some(l) => attr::list_contains_name(&l[..], "hidden"),
|
||||
}
|
||||
});
|
||||
self.doc_hidden_stack.push(doc_hidden);
|
||||
|
|
@ -1145,7 +1145,7 @@ impl LintPass for UnstableFeatures {
|
|||
|
||||
impl LateLintPass for UnstableFeatures {
|
||||
fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
|
||||
if attr::contains_name(&[attr.meta().clone()], "feature") {
|
||||
if attr.meta().check_name("feature") {
|
||||
if let Some(items) = attr.meta().meta_item_list() {
|
||||
for item in items {
|
||||
ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ use lint::{LintPass, EarlyLintPass, LateLintPass};
|
|||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -234,10 +235,13 @@ impl LintPass for UnusedAttributes {
|
|||
|
||||
impl LateLintPass for UnusedAttributes {
|
||||
fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
|
||||
debug!("checking attribute: {:?}", attr);
|
||||
|
||||
// Note that check_name() marks the attribute as used if it matches.
|
||||
for &(ref name, ty, _) in KNOWN_ATTRIBUTES {
|
||||
match ty {
|
||||
AttributeType::Whitelisted if attr.check_name(name) => {
|
||||
debug!("{:?} is Whitelisted", name);
|
||||
break;
|
||||
},
|
||||
_ => ()
|
||||
|
|
@ -247,11 +251,13 @@ impl LateLintPass for UnusedAttributes {
|
|||
let plugin_attributes = cx.sess().plugin_attributes.borrow_mut();
|
||||
for &(ref name, ty) in plugin_attributes.iter() {
|
||||
if ty == AttributeType::Whitelisted && attr.check_name(&name) {
|
||||
debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !attr::is_used(attr) {
|
||||
debug!("Emitting warning for: {:?}", attr);
|
||||
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
|
||||
// Is it a builtin attribute that must be used at the crate level?
|
||||
let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| {
|
||||
|
|
@ -275,6 +281,8 @@ impl LateLintPass for UnusedAttributes {
|
|||
};
|
||||
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
|
||||
}
|
||||
} else {
|
||||
debug!("Attr was used: {:?}", attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -392,13 +400,9 @@ impl LateLintPass for UnusedImportBraces {
|
|||
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
|
||||
if let hir::ItemUse(ref view_path) = item.node {
|
||||
if let hir::ViewPathList(_, ref items) = view_path.node {
|
||||
if items.len() == 1 {
|
||||
if let hir::PathListIdent {ref name, ..} = items[0].node {
|
||||
let m = format!("braces around {} is unnecessary",
|
||||
name);
|
||||
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
|
||||
&m[..]);
|
||||
}
|
||||
if items.len() == 1 && items[0].node.name != keywords::SelfValue.name() {
|
||||
let msg = format!("braces around {} is unnecessary", items[0].node.name);
|
||||
cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,26 +45,13 @@ pub const tag_items_closure_kind: usize = 0x2a;
|
|||
pub const tag_items_closure_ty: usize = 0x2b;
|
||||
pub const tag_def_key: usize = 0x2c;
|
||||
|
||||
// GAP 0x2d 0x2e
|
||||
// GAP 0x2d 0x34
|
||||
|
||||
pub const tag_index: usize = 0x110; // top-level only
|
||||
pub const tag_xref_index: usize = 0x111; // top-level only
|
||||
pub const tag_xref_data: usize = 0x112; // top-level only
|
||||
|
||||
pub const tag_meta_item_name_value: usize = 0x2f;
|
||||
|
||||
pub const tag_meta_item_name: usize = 0x30;
|
||||
|
||||
pub const tag_meta_item_value: usize = 0x31;
|
||||
|
||||
pub const tag_attributes: usize = 0x101; // top-level only
|
||||
|
||||
pub const tag_attribute: usize = 0x32;
|
||||
|
||||
pub const tag_meta_item_word: usize = 0x33;
|
||||
|
||||
pub const tag_meta_item_list: usize = 0x34;
|
||||
|
||||
// The list of crates that this crate depends on
|
||||
pub const tag_crate_deps: usize = 0x102; // top-level only
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ use syntax::abi::Abi;
|
|||
use syntax::codemap;
|
||||
use syntax::parse;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::visit;
|
||||
use syntax_pos::{self, Span, mk_sp, Pos};
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ use syntax::parse::token;
|
|||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
|
||||
|
||||
pub type Cmd<'a> = &'a CrateMetadata;
|
||||
|
|
@ -1113,44 +1112,20 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec<ast::Name> {
|
|||
})).collect()
|
||||
}
|
||||
|
||||
fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
|
||||
reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| {
|
||||
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
|
||||
let n = token::intern_and_get_ident(nd.as_str());
|
||||
attr::mk_word_item(n)
|
||||
}).chain(reader::tagged_docs(md, tag_meta_item_name_value).map(|meta_item_doc| {
|
||||
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
|
||||
let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
|
||||
let n = token::intern_and_get_ident(nd.as_str());
|
||||
let v = token::intern_and_get_ident(vd.as_str());
|
||||
// FIXME (#623): Should be able to decode MetaItemKind::NameValue variants,
|
||||
// but currently the encoder just drops them
|
||||
attr::mk_name_value_item_str(n, v)
|
||||
})).chain(reader::tagged_docs(md, tag_meta_item_list).map(|meta_item_doc| {
|
||||
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
|
||||
let n = token::intern_and_get_ident(nd.as_str());
|
||||
let subitems = get_meta_items(meta_item_doc);
|
||||
attr::mk_list_item(n, subitems)
|
||||
})).collect()
|
||||
}
|
||||
|
||||
fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
|
||||
match reader::maybe_get_doc(md, tag_attributes) {
|
||||
Some(attrs_d) => {
|
||||
reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| {
|
||||
let is_sugared_doc = reader::doc_as_u8(
|
||||
reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
|
||||
) == 1;
|
||||
let meta_items = get_meta_items(attr_doc);
|
||||
// Currently it's only possible to have a single meta item on
|
||||
// an attribute
|
||||
assert_eq!(meta_items.len(), 1);
|
||||
let meta_item = meta_items.into_iter().nth(0).unwrap();
|
||||
attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
|
||||
}).collect()
|
||||
},
|
||||
None => vec![],
|
||||
}
|
||||
reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| {
|
||||
let mut decoder = reader::Decoder::new(attrs_doc);
|
||||
let mut attrs: Vec<ast::Attribute> = decoder.read_opaque(|opaque_decoder, _| {
|
||||
Decodable::decode(opaque_decoder)
|
||||
}).unwrap();
|
||||
|
||||
// Need new unique IDs: old thread-local IDs won't map to new threads.
|
||||
for attr in attrs.iter_mut() {
|
||||
attr.node.id = attr::mk_attr_id();
|
||||
}
|
||||
|
||||
attrs
|
||||
})
|
||||
}
|
||||
|
||||
fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ use std::io::{Cursor, SeekFrom};
|
|||
use std::rc::Rc;
|
||||
use std::u32;
|
||||
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
|
||||
use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
|
||||
use syntax::attr;
|
||||
use errors::Handler;
|
||||
use syntax;
|
||||
use syntax_pos::BytePos;
|
||||
|
|
@ -1417,40 +1417,11 @@ fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
|
|||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
|
||||
if mi.is_word() {
|
||||
let name = mi.name();
|
||||
rbml_w.start_tag(tag_meta_item_word);
|
||||
rbml_w.wr_tagged_str(tag_meta_item_name, &name);
|
||||
rbml_w.end_tag();
|
||||
} else if mi.is_value_str() {
|
||||
let name = mi.name();
|
||||
/* FIXME (#623): support other literal kinds */
|
||||
let value = mi.value_str().unwrap();
|
||||
rbml_w.start_tag(tag_meta_item_name_value);
|
||||
rbml_w.wr_tagged_str(tag_meta_item_name, &name);
|
||||
rbml_w.wr_tagged_str(tag_meta_item_value, &value);
|
||||
rbml_w.end_tag();
|
||||
} else { // it must be a list
|
||||
let name = mi.name();
|
||||
let items = mi.meta_item_list().unwrap();
|
||||
rbml_w.start_tag(tag_meta_item_list);
|
||||
rbml_w.wr_tagged_str(tag_meta_item_name, &name);
|
||||
for inner_item in items {
|
||||
encode_meta_item(rbml_w, &inner_item);
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
|
||||
rbml_w.start_tag(tag_attributes);
|
||||
for attr in attrs {
|
||||
rbml_w.start_tag(tag_attribute);
|
||||
rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
|
||||
encode_meta_item(rbml_w, attr.meta());
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
rbml_w.emit_opaque(|opaque_encoder| {
|
||||
attrs.encode(opaque_encoder)
|
||||
}).unwrap();
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use rustc::util::nodemap::{FnvHashSet, FnvHashMap};
|
|||
use syntax::parse::token;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -64,8 +63,8 @@ impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
|
|||
}
|
||||
if let (Some(sel), Some(names)) = (import.as_mut(), names) {
|
||||
for attr in names {
|
||||
if attr.is_word() {
|
||||
sel.insert(attr.name().clone(), attr.span());
|
||||
if let Some(word) = attr.word() {
|
||||
sel.insert(word.name().clone(), attr.span());
|
||||
} else {
|
||||
span_err!(self.sess, attr.span(), E0466, "bad macro import");
|
||||
}
|
||||
|
|
@ -82,8 +81,8 @@ impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
|
|||
};
|
||||
|
||||
for attr in names {
|
||||
if attr.is_word() {
|
||||
reexport.insert(attr.name().clone(), attr.span());
|
||||
if let Some(word) = attr.word() {
|
||||
reexport.insert(word.name().clone(), attr.span());
|
||||
} else {
|
||||
call_bad_macro_reexport(self.sess, attr.span());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ use rustc::ty::{self, Ty, TyCtxt};
|
|||
use syntax::parse::token;
|
||||
use rustc::hir;
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use rustc::lint;
|
|||
use rustc::session::Session;
|
||||
use syntax::ast::*;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::parse::token::{self, keywords};
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax_pos::Span;
|
||||
|
|
@ -69,6 +70,18 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
|
||||
match constness.node {
|
||||
Constness::Const => {
|
||||
struct_span_err!(self.session, constness.span, E0379,
|
||||
"trait fns cannot be declared const")
|
||||
.span_label(constness.span, &format!("trait fns cannot be const"))
|
||||
.emit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor for AstValidator<'a> {
|
||||
|
|
@ -146,6 +159,9 @@ impl<'a> Visitor for AstValidator<'a> {
|
|||
self.invalid_visibility(&item.vis, item.span, None);
|
||||
for impl_item in impl_items {
|
||||
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
|
||||
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
self.check_trait_fn_not_const(sig.constness);
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemKind::Impl(_, _, _, None, _, _) => {
|
||||
|
|
@ -169,6 +185,13 @@ impl<'a> Visitor for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ItemKind::Trait(_, _, _, ref trait_items) => {
|
||||
for trait_item in trait_items {
|
||||
if let TraitItemKind::Method(ref sig, _) = trait_item.node {
|
||||
self.check_trait_fn_not_const(sig.constness);
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemKind::Mod(_) => {
|
||||
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
|
||||
attr::first_attr_value_str_by_name(&item.attrs, "path");
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
|
|||
}
|
||||
|
||||
let mode = match fk {
|
||||
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => Mode::ConstFn,
|
||||
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _)
|
||||
=> Mode::ConstFn,
|
||||
FnKind::Method(_, m, _, _) => {
|
||||
if m.constness == hir::Constness::Const {
|
||||
Mode::ConstFn
|
||||
|
|
|
|||
|
|
@ -176,6 +176,13 @@ fn some_func() {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0379: r##"
|
||||
Trait methods cannot be declared `const` by design. For more information, see
|
||||
[RFC 911].
|
||||
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
|
||||
"##,
|
||||
|
||||
E0449: r##"
|
||||
A visibility qualifier was used when it was unnecessary. Erroneous code
|
||||
examples:
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ use std::env;
|
|||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax_pos::{Span, COMMAND_LINE_SP};
|
||||
|
||||
/// Pointer to a registrar function.
|
||||
|
|
@ -30,7 +28,7 @@ pub type PluginRegistrarFun =
|
|||
|
||||
pub struct PluginRegistrar {
|
||||
pub fun: PluginRegistrarFun,
|
||||
pub args: Vec<P<ast::MetaItem>>,
|
||||
pub args: Vec<ast::NestedMetaItem>,
|
||||
}
|
||||
|
||||
struct PluginLoader<'a> {
|
||||
|
|
@ -69,13 +67,14 @@ pub fn load_plugins(sess: &Session,
|
|||
};
|
||||
|
||||
for plugin in plugins {
|
||||
if plugin.value_str().is_some() {
|
||||
call_malformed_plugin_attribute(sess, attr.span);
|
||||
continue;
|
||||
// plugins must have a name and can't be key = value
|
||||
match plugin.name() {
|
||||
Some(ref name) if !plugin.is_value_str() => {
|
||||
let args = plugin.meta_item_list().map(ToOwned::to_owned);
|
||||
loader.load_plugin(plugin.span, name, args.unwrap_or_default());
|
||||
},
|
||||
_ => call_malformed_plugin_attribute(sess, attr.span),
|
||||
}
|
||||
|
||||
let args = plugin.meta_item_list().map(ToOwned::to_owned).unwrap_or_default();
|
||||
loader.load_plugin(plugin.span, &plugin.name(), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -102,7 +101,7 @@ impl<'a> PluginLoader<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) {
|
||||
fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
|
||||
let registrar = self.reader.find_plugin_registrar(span, name);
|
||||
|
||||
if let Some((lib, svh, index)) = registrar {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
|||
use syntax::ext::base::{IdentTT, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{MacroExpanderFn, MacroRulesTT};
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use syntax::ast;
|
||||
use syntax::feature_gate::AttributeType;
|
||||
use syntax_pos::Span;
|
||||
|
|
@ -41,7 +40,7 @@ pub struct Registry<'a> {
|
|||
pub sess: &'a Session,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub args_hidden: Option<Vec<P<ast::MetaItem>>>,
|
||||
pub args_hidden: Option<Vec<ast::NestedMetaItem>>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub krate_span: Span,
|
||||
|
|
@ -95,7 +94,7 @@ impl<'a> Registry<'a> {
|
|||
///
|
||||
/// Returns empty slice in case the plugin was loaded
|
||||
/// with `--extra-plugins`
|
||||
pub fn args<'b>(&'b self) -> &'b [P<ast::MetaItem>] {
|
||||
pub fn args<'b>(&'b self) -> &'b [ast::NestedMetaItem] {
|
||||
self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ use syntax::parse::token;
|
|||
|
||||
use syntax::ast::{Block, Crate};
|
||||
use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
|
||||
use syntax::ast::{Mutability, PathListItemKind};
|
||||
use syntax::ast::{StmtKind, TraitItemKind};
|
||||
use syntax::ast::{Mutability, StmtKind, TraitItemKind};
|
||||
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
|
@ -130,9 +130,10 @@ impl<'b> Resolver<'b> {
|
|||
ViewPathList(_, ref source_items) => {
|
||||
// Make sure there's at most one `mod` import in the list.
|
||||
let mod_spans = source_items.iter().filter_map(|item| {
|
||||
match item.node {
|
||||
PathListItemKind::Mod { .. } => Some(item.span),
|
||||
_ => None,
|
||||
if item.node.name.name == keywords::SelfValue.name() {
|
||||
Some(item.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect::<Vec<Span>>();
|
||||
|
||||
|
|
@ -147,10 +148,12 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
|
||||
for source_item in source_items {
|
||||
let (module_path, name, rename) = match source_item.node {
|
||||
PathListItemKind::Ident { name, rename, .. } =>
|
||||
(module_path.clone(), name.name, rename.unwrap_or(name).name),
|
||||
PathListItemKind::Mod { rename, .. } => {
|
||||
let node = source_item.node;
|
||||
let (module_path, name, rename) = {
|
||||
if node.name.name != keywords::SelfValue.name() {
|
||||
let rename = node.rename.unwrap_or(node.name).name;
|
||||
(module_path.clone(), node.name.name, rename)
|
||||
} else {
|
||||
let name = match module_path.last() {
|
||||
Some(name) => *name,
|
||||
None => {
|
||||
|
|
@ -164,12 +167,12 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
};
|
||||
let module_path = module_path.split_last().unwrap().1;
|
||||
let rename = rename.map(|i| i.name).unwrap_or(name);
|
||||
let rename = node.rename.map(|i| i.name).unwrap_or(name);
|
||||
(module_path.to_vec(), name, rename)
|
||||
}
|
||||
};
|
||||
let subclass = ImportDirectiveSubclass::single(rename, name);
|
||||
let (span, id) = (source_item.span, source_item.node.id());
|
||||
let (span, id) = (source_item.span, source_item.node.id);
|
||||
self.add_import_directive(module_path, subclass, span, id, vis);
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +275,8 @@ impl<'b> Resolver<'b> {
|
|||
self.structs.insert(item_def_id, field_names);
|
||||
}
|
||||
|
||||
ItemKind::Union(..) => panic!("`union` is not yet implemented"),
|
||||
|
||||
ItemKind::DefaultImpl(_, _) | ItemKind::Impl(..) => {}
|
||||
|
||||
ItemKind::Trait(_, _, _, ref items) => {
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl<'a, 'b> Visitor for UnusedImportCheckVisitor<'a, 'b> {
|
|||
|
||||
ViewPathList(_, ref list) => {
|
||||
for i in list {
|
||||
self.check_import(i.node.id(), i.span);
|
||||
self.check_import(i.node.id, i.span);
|
||||
}
|
||||
}
|
||||
ViewPathGlob(_) => {
|
||||
|
|
|
|||
|
|
@ -1618,6 +1618,7 @@ impl<'a> Resolver<'a> {
|
|||
ItemKind::Enum(_, ref generics) |
|
||||
ItemKind::Ty(_, ref generics) |
|
||||
ItemKind::Struct(_, ref generics) |
|
||||
ItemKind::Union(_, ref generics) |
|
||||
ItemKind::Fn(_, _, _, _, ref generics, _) => {
|
||||
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
|
||||
|this| visit::walk_item(this, item));
|
||||
|
|
|
|||
|
|
@ -1102,18 +1102,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
|
|||
}
|
||||
ast::ViewPathList(ref path, ref list) => {
|
||||
for plid in list {
|
||||
match plid.node {
|
||||
ast::PathListItemKind::Ident { id, .. } => {
|
||||
let scope = self.cur_scope;
|
||||
if let Some(def_id) = self.lookup_type_ref(id) {
|
||||
self.process_def_kind(id,
|
||||
plid.span,
|
||||
Some(plid.span),
|
||||
def_id,
|
||||
scope);
|
||||
}
|
||||
}
|
||||
ast::PathListItemKind::Mod { .. } => (),
|
||||
let scope = self.cur_scope;
|
||||
let id = plid.node.id;
|
||||
if let Some(def_id) = self.lookup_type_ref(id) {
|
||||
let span = plid.span;
|
||||
self.process_def_kind(id, span, Some(span), def_id, scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
use rustc::ty::TyCtxt;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
use {ModuleSource, ModuleTranslation};
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ use std::process::Command;
|
|||
use std::str;
|
||||
use flate;
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax_pos::Span;
|
||||
|
||||
// RLIB LLVM-BYTECODE OBJECT LAYOUT
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ use std::rc::Rc;
|
|||
use std::str;
|
||||
use std::i32;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::attr;
|
||||
use rustc::hir;
|
||||
use syntax::ast;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use rustc::hir;
|
|||
|
||||
use std::ffi::{CStr, CString};
|
||||
use syntax::ast;
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token;
|
||||
|
||||
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor};
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
use common::SharedCrateContext;
|
||||
use monomorphize::Instance;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
let i_n_tps = i_ty.generics.types.len();
|
||||
if i_n_tps != n_tps {
|
||||
let span = match it.node {
|
||||
hir::ForeignItemFn(_, ref generics) => generics.span().unwrap_or(it.span),
|
||||
hir::ForeignItemFn(_, ref generics) => generics.span,
|
||||
hir::ForeignItemStatic(_, _) => it.span
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ use std::ops::Deref;
|
|||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::{self, Spanned};
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax::parse::token::{self, InternedString, keywords};
|
||||
|
|
@ -835,13 +834,9 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
|||
check_const(ccx, &expr, trait_item.id)
|
||||
}
|
||||
hir::MethodTraitItem(ref sig, Some(ref body)) => {
|
||||
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
|
||||
|
||||
check_bare_fn(ccx, &sig.decl, body, trait_item.id);
|
||||
}
|
||||
hir::MethodTraitItem(ref sig, None) => {
|
||||
check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
|
||||
}
|
||||
hir::MethodTraitItem(_, None) |
|
||||
hir::ConstTraitItem(_, None) |
|
||||
hir::TypeTraitItem(..) => {
|
||||
// Nothing to do.
|
||||
|
|
@ -853,22 +848,6 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
constness: hir::Constness)
|
||||
{
|
||||
match constness {
|
||||
hir::Constness::NotConst => {
|
||||
// good
|
||||
}
|
||||
hir::Constness::Const => {
|
||||
struct_span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const")
|
||||
.span_label(span, &format!("trait fns cannot be const"))
|
||||
.emit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
item: &hir::Item) {
|
||||
|
|
@ -1026,9 +1005,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
err.emit()
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
|
||||
|
||||
hir::ImplItemKind::Method(_, ref body) => {
|
||||
let impl_method = match ty_impl_item {
|
||||
ty::MethodTraitItem(ref mti) => mti,
|
||||
_ => span_bug!(impl_item.span, "non-method impl-item for method")
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
|
|||
}
|
||||
hir::ViewPathList(_, ref path_list) => {
|
||||
for path_item in path_list {
|
||||
self.check_import(path_item.node.id(), path_item.span);
|
||||
self.check_import(path_item.node.id, path_item.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3422,13 +3422,6 @@ containing the unsized type is the last and only unsized type field in the
|
|||
struct.
|
||||
"##,
|
||||
|
||||
E0379: r##"
|
||||
Trait methods cannot be declared `const` by design. For more information, see
|
||||
[RFC 911].
|
||||
|
||||
[RFC 911]: https://github.com/rust-lang/rfcs/pull/911
|
||||
"##,
|
||||
|
||||
E0380: r##"
|
||||
Default impls are only allowed for traits with no methods or associated items.
|
||||
For more information see the [opt-in builtin traits RFC](https://github.com/rust
|
||||
|
|
|
|||
|
|
@ -216,10 +216,10 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
|
|||
Some(hir_map::NodeItem(it)) => {
|
||||
match it.node {
|
||||
hir::ItemFn(_, _, _, _, ref generics, _) => {
|
||||
if let Some(gen_span) = generics.span() {
|
||||
struct_span_err!(ccx.tcx.sess, gen_span, E0131,
|
||||
if generics.is_parameterized() {
|
||||
struct_span_err!(ccx.tcx.sess, generics.span, E0131,
|
||||
"main function is not allowed to have type parameters")
|
||||
.span_label(gen_span,
|
||||
.span_label(generics.span,
|
||||
&format!("main cannot have type parameters"))
|
||||
.emit();
|
||||
return;
|
||||
|
|
@ -269,10 +269,9 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
|
|||
match it.node {
|
||||
hir::ItemFn(_,_,_,_,ref ps,_)
|
||||
if ps.is_parameterized() => {
|
||||
let sp = if let Some(sp) = ps.span() { sp } else { start_span };
|
||||
struct_span_err!(tcx.sess, sp, E0132,
|
||||
struct_span_err!(tcx.sess, ps.span, E0132,
|
||||
"start function is not allowed to have type parameters")
|
||||
.span_label(sp,
|
||||
.span_label(ps.span,
|
||||
&format!("start function cannot have type parameters"))
|
||||
.emit();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@ pub use self::Visibility::*;
|
|||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::{AttributeMethods, AttrMetaMethods};
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::parse::token::{self, InternedString, keywords};
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
use syntax::print::pprust as syntax_pprust;
|
||||
use syntax_pos::{self, DUMMY_SP, Pos};
|
||||
|
||||
use rustc_trans::back::link;
|
||||
|
|
@ -501,11 +501,24 @@ impl Attributes for [Attribute] {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is a flattened version of the AST's Attribute + MetaItem.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
pub enum Attribute {
|
||||
Word(String),
|
||||
List(String, Vec<Attribute>),
|
||||
NameValue(String, String)
|
||||
NameValue(String, String),
|
||||
Literal(String),
|
||||
}
|
||||
|
||||
impl Clean<Attribute> for ast::NestedMetaItem {
|
||||
fn clean(&self, cx: &DocContext) -> Attribute {
|
||||
if let Some(mi) = self.meta_item() {
|
||||
mi.clean(cx)
|
||||
} else { // must be a literal
|
||||
let lit = self.literal().unwrap();
|
||||
Literal(syntax_pprust::lit_to_string(lit))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Attribute> for ast::MetaItem {
|
||||
|
|
@ -527,50 +540,6 @@ impl Clean<Attribute> for ast::Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
// This is a rough approximation that gets us what we want.
|
||||
impl attr::AttrMetaMethods for Attribute {
|
||||
fn name(&self) -> InternedString {
|
||||
match *self {
|
||||
Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
|
||||
token::intern_and_get_ident(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn value_str(&self) -> Option<InternedString> {
|
||||
match *self {
|
||||
NameValue(_, ref v) => {
|
||||
Some(token::intern_and_get_ident(v))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
|
||||
|
||||
fn is_word(&self) -> bool {
|
||||
match *self {
|
||||
Word(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_value_str(&self) -> bool {
|
||||
match *self {
|
||||
NameValue(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_meta_item_list(&self) -> bool {
|
||||
match *self {
|
||||
List(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn span(&self) -> syntax_pos::Span { unimplemented!() }
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
pub struct TyParam {
|
||||
pub name: String,
|
||||
|
|
@ -2534,8 +2503,8 @@ impl Clean<Vec<Item>> for doctree::Import {
|
|||
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
|
||||
let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
|
||||
&a.name()[..] == "doc" && match a.meta_item_list() {
|
||||
Some(l) => attr::contains_name(l, "no_inline") ||
|
||||
attr::contains_name(l, "hidden"),
|
||||
Some(l) => attr::list_contains_name(l, "no_inline") ||
|
||||
attr::list_contains_name(l, "hidden"),
|
||||
None => false,
|
||||
}
|
||||
});
|
||||
|
|
@ -2551,7 +2520,7 @@ impl Clean<Vec<Item>> for doctree::Import {
|
|||
let remaining = if !denied {
|
||||
let mut remaining = vec![];
|
||||
for path in list {
|
||||
match inline::try_inline(cx, path.node.id(), path.node.rename()) {
|
||||
match inline::try_inline(cx, path.node.id, path.node.rename) {
|
||||
Some(items) => {
|
||||
ret.extend(items);
|
||||
}
|
||||
|
|
@ -2619,17 +2588,10 @@ pub struct ViewListIdent {
|
|||
|
||||
impl Clean<ViewListIdent> for hir::PathListItem {
|
||||
fn clean(&self, cx: &DocContext) -> ViewListIdent {
|
||||
match self.node {
|
||||
hir::PathListIdent { id, name, rename } => ViewListIdent {
|
||||
name: name.clean(cx),
|
||||
rename: rename.map(|r| r.clean(cx)),
|
||||
source: resolve_def(cx, id)
|
||||
},
|
||||
hir::PathListMod { id, rename } => ViewListIdent {
|
||||
name: "self".to_string(),
|
||||
rename: rename.map(|r| r.clean(cx)),
|
||||
source: resolve_def(cx, id)
|
||||
}
|
||||
ViewListIdent {
|
||||
name: self.node.name.clean(cx),
|
||||
rename: self.node.rename.map(|r| r.clean(cx)),
|
||||
source: resolve_def(cx, self.node.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ pub fn run(input: &str,
|
|||
|
||||
// Look for #![doc(test(no_crate_inject))], used by crates in the std facade
|
||||
fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::print::pprust;
|
||||
|
||||
let mut opts = TestOptions {
|
||||
|
|
@ -162,7 +161,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
|
|||
if attr.check_name("attr") {
|
||||
if let Some(l) = attr.meta_item_list() {
|
||||
for item in l {
|
||||
opts.attrs.push(pprust::meta_item_to_string(item));
|
||||
opts.attrs.push(pprust::meta_list_item_to_string(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use std::mem;
|
|||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir::map as hir_map;
|
||||
|
|
@ -189,7 +188,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
}
|
||||
hir::ViewPathList(p, paths) => {
|
||||
let mine = paths.into_iter().filter(|path| {
|
||||
!self.maybe_inline_local(path.node.id(), path.node.rename(),
|
||||
!self.maybe_inline_local(path.node.id, path.node.rename,
|
||||
false, om, please_inline)
|
||||
}).collect::<hir::HirVec<hir::PathListItem>>();
|
||||
|
||||
|
|
@ -333,8 +332,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
let node = if item.vis == hir::Public {
|
||||
let please_inline = item.attrs.iter().any(|item| {
|
||||
match item.meta_item_list() {
|
||||
Some(list) if &item.name()[..] == "doc" => {
|
||||
list.iter().any(|i| &i.name()[..] == "inline")
|
||||
Some(list) if item.check_name("doc") => {
|
||||
list.iter().any(|i| i.check_name("inline"))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ pub struct TyParam {
|
|||
pub id: NodeId,
|
||||
pub bounds: TyParamBounds,
|
||||
pub default: Option<P<Ty>>,
|
||||
pub span: Span
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Represents lifetimes and type parameters attached to a declaration
|
||||
|
|
@ -346,6 +346,7 @@ pub struct Generics {
|
|||
pub lifetimes: Vec<LifetimeDef>,
|
||||
pub ty_params: P<[TyParam]>,
|
||||
pub where_clause: WhereClause,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
|
|
@ -368,7 +369,8 @@ impl Default for Generics {
|
|||
where_clause: WhereClause {
|
||||
id: DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
}
|
||||
},
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -439,6 +441,22 @@ pub struct Crate {
|
|||
pub exported_macros: Vec<MacroDef>,
|
||||
}
|
||||
|
||||
/// A spanned compile-time attribute list item.
|
||||
pub type NestedMetaItem = Spanned<NestedMetaItemKind>;
|
||||
|
||||
/// Possible values inside of compile-time attribute lists.
|
||||
///
|
||||
/// E.g. the '..' in `#[name(..)]`.
|
||||
#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialEq)]
|
||||
pub enum NestedMetaItemKind {
|
||||
/// A full MetaItem, for recursive meta items.
|
||||
MetaItem(P<MetaItem>),
|
||||
/// A literal.
|
||||
///
|
||||
/// E.g. "foo", 64, true
|
||||
Literal(Lit),
|
||||
}
|
||||
|
||||
/// A spanned compile-time attribute item.
|
||||
///
|
||||
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
|
||||
|
|
@ -456,7 +474,7 @@ pub enum MetaItemKind {
|
|||
/// List meta item.
|
||||
///
|
||||
/// E.g. `derive(..)` as in `#[derive(..)]`
|
||||
List(InternedString, Vec<P<MetaItem>>),
|
||||
List(InternedString, Vec<NestedMetaItem>),
|
||||
/// Name value meta item.
|
||||
///
|
||||
/// E.g. `feature = "foo"` as in `#[feature = "foo"]`
|
||||
|
|
@ -472,19 +490,21 @@ impl PartialEq for MetaItemKind {
|
|||
Word(ref no) => (*ns) == (*no),
|
||||
_ => false
|
||||
},
|
||||
List(ref ns, ref miss) => match *other {
|
||||
List(ref no, ref miso) => {
|
||||
ns == no &&
|
||||
miss.iter().all(|mi| {
|
||||
miso.iter().any(|x| x.node == mi.node)
|
||||
})
|
||||
}
|
||||
_ => false
|
||||
},
|
||||
NameValue(ref ns, ref vs) => match *other {
|
||||
NameValue(ref no, ref vo) => {
|
||||
(*ns) == (*no) && vs.node == vo.node
|
||||
}
|
||||
_ => false
|
||||
},
|
||||
List(ref ns, ref miss) => match *other {
|
||||
List(ref no, ref miso) => {
|
||||
ns == no &&
|
||||
miss.iter().all(|mi| miso.iter().any(|x| x.node == mi.node))
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1105,6 +1125,30 @@ impl LitKind {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this literal has no suffix. Note: this will return true
|
||||
/// for literals with prefixes such as raw strings and byte strings.
|
||||
pub fn is_unsuffixed(&self) -> bool {
|
||||
match *self {
|
||||
// unsuffixed variants
|
||||
LitKind::Str(..) => true,
|
||||
LitKind::ByteStr(..) => true,
|
||||
LitKind::Byte(..) => true,
|
||||
LitKind::Char(..) => true,
|
||||
LitKind::Int(_, LitIntType::Unsuffixed) => true,
|
||||
LitKind::FloatUnsuffixed(..) => true,
|
||||
LitKind::Bool(..) => true,
|
||||
// suffixed variants
|
||||
LitKind::Int(_, LitIntType::Signed(..)) => false,
|
||||
LitKind::Int(_, LitIntType::Unsigned(..)) => false,
|
||||
LitKind::Float(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this literal has a suffix.
|
||||
pub fn is_suffixed(&self) -> bool {
|
||||
!self.is_unsuffixed()
|
||||
}
|
||||
}
|
||||
|
||||
// NB: If you change this, you'll probably want to change the corresponding
|
||||
|
|
@ -1120,7 +1164,7 @@ pub struct MutTy {
|
|||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct MethodSig {
|
||||
pub unsafety: Unsafety,
|
||||
pub constness: Constness,
|
||||
pub constness: Spanned<Constness>,
|
||||
pub abi: Abi,
|
||||
pub decl: P<FnDecl>,
|
||||
pub generics: Generics,
|
||||
|
|
@ -1624,42 +1668,14 @@ pub struct Variant_ {
|
|||
pub type Variant = Spanned<Variant_>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
pub enum PathListItemKind {
|
||||
Ident {
|
||||
name: Ident,
|
||||
/// renamed in list, e.g. `use foo::{bar as baz};`
|
||||
rename: Option<Ident>,
|
||||
id: NodeId
|
||||
},
|
||||
Mod {
|
||||
/// renamed in list, e.g. `use foo::{self as baz};`
|
||||
rename: Option<Ident>,
|
||||
id: NodeId
|
||||
}
|
||||
pub struct PathListItem_ {
|
||||
pub name: Ident,
|
||||
/// renamed in list, e.g. `use foo::{bar as baz};`
|
||||
pub rename: Option<Ident>,
|
||||
pub id: NodeId,
|
||||
}
|
||||
|
||||
impl PathListItemKind {
|
||||
pub fn id(&self) -> NodeId {
|
||||
match *self {
|
||||
PathListItemKind::Ident { id, .. } | PathListItemKind::Mod { id, .. } => id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<Ident> {
|
||||
match *self {
|
||||
PathListItemKind::Ident { name, .. } => Some(name),
|
||||
PathListItemKind::Mod { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename(&self) -> Option<Ident> {
|
||||
match *self {
|
||||
PathListItemKind::Ident { rename, .. } | PathListItemKind::Mod { rename, .. } => rename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type PathListItem = Spanned<PathListItemKind>;
|
||||
pub type PathListItem = Spanned<PathListItem_>;
|
||||
|
||||
pub type ViewPath = Spanned<ViewPath_>;
|
||||
|
||||
|
|
@ -1846,7 +1862,7 @@ pub enum ItemKind {
|
|||
/// A function declaration (`fn` or `pub fn`).
|
||||
///
|
||||
/// E.g. `fn foo(bar: usize) -> usize { .. }`
|
||||
Fn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
|
||||
Fn(P<FnDecl>, Unsafety, Spanned<Constness>, Abi, Generics, P<Block>),
|
||||
/// A module declaration (`mod` or `pub mod`).
|
||||
///
|
||||
/// E.g. `mod foo;` or `mod foo { .. }`
|
||||
|
|
@ -1867,6 +1883,10 @@ pub enum ItemKind {
|
|||
///
|
||||
/// E.g. `struct Foo<A> { x: A }`
|
||||
Struct(VariantData, Generics),
|
||||
/// A union definition (`union` or `pub union`).
|
||||
///
|
||||
/// E.g. `union Foo<A, B> { x: A, y: B }`
|
||||
Union(VariantData, Generics), // FIXME: not yet implemented
|
||||
/// A Trait declaration (`trait` or `pub trait`).
|
||||
///
|
||||
/// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
|
||||
|
|
@ -1903,6 +1923,7 @@ impl ItemKind {
|
|||
ItemKind::Ty(..) => "type alias",
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
ItemKind::Union(..) => "union",
|
||||
ItemKind::Trait(..) => "trait",
|
||||
ItemKind::Mac(..) |
|
||||
ItemKind::Impl(..) |
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@ pub use self::ReprAttr::*;
|
|||
pub use self::IntType::*;
|
||||
|
||||
use ast;
|
||||
use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
|
||||
use ast::{Expr, Item, Local, Stmt, StmtKind};
|
||||
use codemap::{respan, spanned, dummy_spanned, Spanned};
|
||||
use ast::{AttrId, Attribute, Attribute_};
|
||||
use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
|
||||
use ast::{Lit, Expr, Item, Local, Stmt, StmtKind};
|
||||
use codemap::{respan, spanned, dummy_spanned};
|
||||
use syntax_pos::{Span, BytePos, DUMMY_SP};
|
||||
use errors::Handler;
|
||||
use feature_gate::{Features, GatedCfg};
|
||||
|
|
@ -40,6 +41,7 @@ enum AttrError {
|
|||
MissingSince,
|
||||
MissingFeature,
|
||||
MultipleStabilityLevels,
|
||||
UnsupportedLiteral
|
||||
}
|
||||
|
||||
fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
|
||||
|
|
@ -52,10 +54,12 @@ 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"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_used(attr: &Attribute) {
|
||||
debug!("Marking {:?} as used.", attr);
|
||||
let AttrId(id) = attr.node.id;
|
||||
USED_ATTRS.with(|slot| {
|
||||
let idx = (id / 64) as usize;
|
||||
|
|
@ -77,60 +81,120 @@ pub fn is_used(attr: &Attribute) -> bool {
|
|||
})
|
||||
}
|
||||
|
||||
pub trait AttrMetaMethods {
|
||||
fn check_name(&self, name: &str) -> bool {
|
||||
name == &self.name()[..]
|
||||
impl NestedMetaItem {
|
||||
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
|
||||
pub fn meta_item(&self) -> Option<&P<MetaItem>> {
|
||||
match self.node {
|
||||
NestedMetaItemKind::MetaItem(ref item) => Some(&item),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the name of the meta item, e.g. `foo` in `#[foo]`,
|
||||
/// `#[foo="bar"]` and `#[foo(bar)]`
|
||||
fn name(&self) -> InternedString;
|
||||
/// Returns the Lit if self is a NestedMetaItemKind::Literal.
|
||||
pub fn literal(&self) -> Option<&Lit> {
|
||||
match self.node {
|
||||
NestedMetaItemKind::Literal(ref lit) => Some(&lit),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the Span for `self`.
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
/// Returns true if this list item is a MetaItem with a name of `name`.
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
|
||||
}
|
||||
|
||||
/// Returns the name of the meta item, e.g. `foo` in `#[foo]`,
|
||||
/// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
|
||||
pub fn name(&self) -> Option<InternedString> {
|
||||
self.meta_item().and_then(|meta_item| Some(meta_item.name()))
|
||||
}
|
||||
|
||||
/// Gets the string value if self is a MetaItem and the MetaItem is a
|
||||
/// MetaItemKind::NameValue variant containing a string, otherwise None.
|
||||
pub fn value_str(&self) -> Option<InternedString> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.value_str())
|
||||
}
|
||||
|
||||
/// Returns a MetaItem if self is a MetaItem with Kind Word.
|
||||
pub fn word(&self) -> Option<&P<MetaItem>> {
|
||||
self.meta_item().and_then(|meta_item| if meta_item.is_word() {
|
||||
Some(meta_item)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the string value if self is a MetaItemKind::NameValue variant
|
||||
/// containing a string, otherwise None.
|
||||
fn value_str(&self) -> Option<InternedString>;
|
||||
/// Gets a list of inner meta items from a list MetaItem type.
|
||||
fn meta_item_list(&self) -> Option<&[P<MetaItem>]>;
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
|
||||
}
|
||||
|
||||
/// Indicates if the attribute is a Word.
|
||||
fn is_word(&self) -> bool;
|
||||
/// Returns `true` if the variant is MetaItem.
|
||||
pub fn is_meta_item(&self) -> bool {
|
||||
self.meta_item().is_some()
|
||||
}
|
||||
|
||||
/// Indicates if the attribute is a Value String.
|
||||
fn is_value_str(&self) -> bool {
|
||||
/// Returns `true` if the variant is Literal.
|
||||
pub fn is_literal(&self) -> bool {
|
||||
self.literal().is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if self is a MetaItem and the meta item is a word.
|
||||
pub fn is_word(&self) -> bool {
|
||||
self.word().is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if self is a MetaItem and the meta item is a ValueString.
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
/// Indicates if the attribute is a Meta-Item List.
|
||||
fn is_meta_item_list(&self) -> bool {
|
||||
/// Returns `true` if self is a MetaItem and the meta item is a list.
|
||||
pub fn is_meta_item_list(&self) -> bool {
|
||||
self.meta_item_list().is_some()
|
||||
}
|
||||
|
||||
fn span(&self) -> Span;
|
||||
}
|
||||
|
||||
impl AttrMetaMethods for Attribute {
|
||||
fn check_name(&self, name: &str) -> bool {
|
||||
impl Attribute {
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
let matches = name == &self.name()[..];
|
||||
if matches {
|
||||
mark_used(self);
|
||||
}
|
||||
matches
|
||||
}
|
||||
fn name(&self) -> InternedString { self.meta().name() }
|
||||
fn value_str(&self) -> Option<InternedString> {
|
||||
|
||||
pub fn name(&self) -> InternedString { self.meta().name() }
|
||||
|
||||
pub fn value_str(&self) -> Option<InternedString> {
|
||||
self.meta().value_str()
|
||||
}
|
||||
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
self.meta().meta_item_list()
|
||||
}
|
||||
|
||||
fn is_word(&self) -> bool { self.meta().is_word() }
|
||||
pub fn is_word(&self) -> bool { self.meta().is_word() }
|
||||
|
||||
fn span(&self) -> Span { self.meta().span }
|
||||
pub fn span(&self) -> Span { self.meta().span }
|
||||
|
||||
pub fn is_meta_item_list(&self) -> bool {
|
||||
self.meta_item_list().is_some()
|
||||
}
|
||||
|
||||
/// Indicates if the attribute is a Value String.
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl AttrMetaMethods for MetaItem {
|
||||
fn name(&self) -> InternedString {
|
||||
impl MetaItem {
|
||||
pub fn name(&self) -> InternedString {
|
||||
match self.node {
|
||||
MetaItemKind::Word(ref n) => (*n).clone(),
|
||||
MetaItemKind::NameValue(ref n, _) => (*n).clone(),
|
||||
|
|
@ -138,7 +202,7 @@ impl AttrMetaMethods for MetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn value_str(&self) -> Option<InternedString> {
|
||||
pub fn value_str(&self) -> Option<InternedString> {
|
||||
match self.node {
|
||||
MetaItemKind::NameValue(_, ref v) => {
|
||||
match v.node {
|
||||
|
|
@ -150,53 +214,45 @@ impl AttrMetaMethods for MetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
|
||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||
match self.node {
|
||||
MetaItemKind::List(_, ref l) => Some(&l[..]),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn is_word(&self) -> bool {
|
||||
pub fn is_word(&self) -> bool {
|
||||
match self.node {
|
||||
MetaItemKind::Word(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn span(&self) -> Span { self.span }
|
||||
}
|
||||
pub fn span(&self) -> Span { self.span }
|
||||
|
||||
// Annoying, but required to get test_cfg to work
|
||||
impl AttrMetaMethods for P<MetaItem> {
|
||||
fn name(&self) -> InternedString { (**self).name() }
|
||||
fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
|
||||
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
|
||||
(**self).meta_item_list()
|
||||
pub fn check_name(&self, name: &str) -> bool {
|
||||
name == &self.name()[..]
|
||||
}
|
||||
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
pub fn is_meta_item_list(&self) -> bool {
|
||||
self.meta_item_list().is_some()
|
||||
}
|
||||
fn is_word(&self) -> bool { (**self).is_word() }
|
||||
fn is_value_str(&self) -> bool { (**self).is_value_str() }
|
||||
fn is_meta_item_list(&self) -> bool { (**self).is_meta_item_list() }
|
||||
fn span(&self) -> Span { (**self).span() }
|
||||
}
|
||||
|
||||
|
||||
pub trait AttributeMethods {
|
||||
fn meta(&self) -> &MetaItem;
|
||||
fn with_desugared_doc<T, F>(&self, f: F) -> T where
|
||||
F: FnOnce(&Attribute) -> T;
|
||||
}
|
||||
|
||||
impl AttributeMethods for Attribute {
|
||||
impl Attribute {
|
||||
/// Extract the MetaItem from inside this Attribute.
|
||||
fn meta(&self) -> &MetaItem {
|
||||
pub fn meta(&self) -> &MetaItem {
|
||||
&self.node.value
|
||||
}
|
||||
|
||||
/// Convert self to a normal #[doc="foo"] comment, if it is a
|
||||
/// comment like `///` or `/** */`. (Returns self unchanged for
|
||||
/// non-sugared doc attributes.)
|
||||
fn with_desugared_doc<T, F>(&self, f: F) -> T where
|
||||
pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
|
||||
F: FnOnce(&Attribute) -> T,
|
||||
{
|
||||
if self.node.is_sugared_doc {
|
||||
|
|
@ -229,10 +285,14 @@ pub fn mk_name_value_item(name: InternedString, value: ast::Lit)
|
|||
mk_spanned_name_value_item(DUMMY_SP, name, value)
|
||||
}
|
||||
|
||||
pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
|
||||
pub fn mk_list_item(name: InternedString, items: Vec<NestedMetaItem>) -> P<MetaItem> {
|
||||
mk_spanned_list_item(DUMMY_SP, name, items)
|
||||
}
|
||||
|
||||
pub fn mk_list_word_item(name: InternedString) -> ast::NestedMetaItem {
|
||||
dummy_spanned(NestedMetaItemKind::MetaItem(mk_spanned_word_item(DUMMY_SP, name)))
|
||||
}
|
||||
|
||||
pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
|
||||
mk_spanned_word_item(DUMMY_SP, name)
|
||||
}
|
||||
|
|
@ -242,7 +302,7 @@ pub fn mk_spanned_name_value_item(sp: Span, name: InternedString, value: ast::Li
|
|||
P(respan(sp, MetaItemKind::NameValue(name, value)))
|
||||
}
|
||||
|
||||
pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec<P<MetaItem>>)
|
||||
pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec<NestedMetaItem>)
|
||||
-> P<MetaItem> {
|
||||
P(respan(sp, MetaItemKind::List(name, items)))
|
||||
}
|
||||
|
|
@ -332,9 +392,17 @@ pub fn contains(haystack: &[P<MetaItem>], needle: &MetaItem) -> bool {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn contains_name<AM: AttrMetaMethods>(metas: &[AM], name: &str) -> bool {
|
||||
pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool {
|
||||
debug!("attr::list_contains_name (name={})", name);
|
||||
items.iter().any(|item| {
|
||||
debug!(" testing: {:?}", item.name());
|
||||
item.check_name(name)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn contains_name(attrs: &[Attribute], name: &str) -> bool {
|
||||
debug!("attr::contains_name (name={})", name);
|
||||
metas.iter().any(|item| {
|
||||
attrs.iter().any(|item| {
|
||||
debug!(" testing: {}", item.name());
|
||||
item.check_name(name)
|
||||
})
|
||||
|
|
@ -357,27 +425,6 @@ pub fn last_meta_item_value_str_by_name(items: &[P<MetaItem>], name: &str)
|
|||
|
||||
/* Higher-level applications */
|
||||
|
||||
pub fn sort_meta_items(items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
|
||||
// This is sort of stupid here, but we need to sort by
|
||||
// human-readable strings.
|
||||
let mut v = items.into_iter()
|
||||
.map(|mi| (mi.name(), mi))
|
||||
.collect::<Vec<(InternedString, P<MetaItem>)>>();
|
||||
|
||||
v.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
|
||||
|
||||
// There doesn't seem to be a more optimal way to do this
|
||||
v.into_iter().map(|(_, m)| m.map(|Spanned {node, span}| {
|
||||
Spanned {
|
||||
node: match node {
|
||||
MetaItemKind::List(n, mis) => MetaItemKind::List(n, sort_meta_items(mis)),
|
||||
_ => node
|
||||
},
|
||||
span: span
|
||||
}
|
||||
})).collect()
|
||||
}
|
||||
|
||||
pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
|
||||
first_attr_value_str_by_name(attrs, "crate_name")
|
||||
}
|
||||
|
|
@ -427,14 +474,15 @@ pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> In
|
|||
if items.len() != 1 {
|
||||
diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
|
||||
InlineAttr::None
|
||||
} else if contains_name(&items[..], "always") {
|
||||
} else if list_contains_name(&items[..], "always") {
|
||||
InlineAttr::Always
|
||||
} else if contains_name(&items[..], "never") {
|
||||
} else if list_contains_name(&items[..], "never") {
|
||||
InlineAttr::Never
|
||||
} else {
|
||||
diagnostic.map(|d| {
|
||||
span_err!(d, (*items[0]).span, E0535, "invalid argument");
|
||||
span_err!(d, items[0].span, E0535, "invalid argument");
|
||||
});
|
||||
|
||||
InlineAttr::None
|
||||
}
|
||||
}
|
||||
|
|
@ -453,27 +501,44 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool {
|
|||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(cfgs: &[P<MetaItem>], cfg: &ast::MetaItem,
|
||||
sess: &ParseSess, features: Option<&Features>)
|
||||
sess: &ParseSess,
|
||||
features: Option<&Features>)
|
||||
-> bool {
|
||||
match cfg.node {
|
||||
ast::MetaItemKind::List(ref pred, ref mis) if &pred[..] == "any" =>
|
||||
mis.iter().any(|mi| cfg_matches(cfgs, &mi, sess, features)),
|
||||
ast::MetaItemKind::List(ref pred, ref mis) if &pred[..] == "all" =>
|
||||
mis.iter().all(|mi| cfg_matches(cfgs, &mi, sess, features)),
|
||||
ast::MetaItemKind::List(ref pred, ref mis) if &pred[..] == "not" => {
|
||||
if mis.len() != 1 {
|
||||
span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
|
||||
return false;
|
||||
ast::MetaItemKind::List(ref pred, ref mis) => {
|
||||
for mi in mis.iter() {
|
||||
if !mi.is_meta_item() {
|
||||
handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The unwraps below may look dangerous, but we've already asserted
|
||||
// that they won't fail with the loop above.
|
||||
match &pred[..] {
|
||||
"any" => mis.iter().any(|mi| {
|
||||
cfg_matches(cfgs, mi.meta_item().unwrap(), sess, features)
|
||||
}),
|
||||
"all" => mis.iter().all(|mi| {
|
||||
cfg_matches(cfgs, mi.meta_item().unwrap(), sess, features)
|
||||
}),
|
||||
"not" => {
|
||||
if mis.len() != 1 {
|
||||
span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
|
||||
return false;
|
||||
}
|
||||
|
||||
!cfg_matches(cfgs, mis[0].meta_item().unwrap(), sess, features)
|
||||
},
|
||||
p => {
|
||||
span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p);
|
||||
false
|
||||
}
|
||||
}
|
||||
!cfg_matches(cfgs, &mis[0], sess, features)
|
||||
}
|
||||
ast::MetaItemKind::List(ref pred, _) => {
|
||||
span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", pred);
|
||||
false
|
||||
},
|
||||
ast::MetaItemKind::Word(_) | ast::MetaItemKind::NameValue(..) => {
|
||||
if let (Some(features), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
|
||||
gated_cfg.check_and_emit(sess, features);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
|
||||
gated_cfg.check_and_emit(sess, feats);
|
||||
}
|
||||
contains(cfgs, cfg)
|
||||
}
|
||||
|
|
@ -557,14 +622,19 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
|
|||
let mut since = None;
|
||||
let mut reason = None;
|
||||
for meta in metas {
|
||||
match &*meta.name() {
|
||||
"since" => if !get(meta, &mut since) { continue 'outer },
|
||||
"reason" => if !get(meta, &mut reason) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, meta.span,
|
||||
AttrError::UnknownMetaItem(meta.name()));
|
||||
continue 'outer
|
||||
if let Some(mi) = meta.meta_item() {
|
||||
match &*mi.name() {
|
||||
"since" => if !get(mi, &mut since) { continue 'outer },
|
||||
"reason" => if !get(mi, &mut reason) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, mi.span,
|
||||
AttrError::UnknownMetaItem(mi.name()));
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -595,15 +665,20 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
|
|||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
for meta in metas {
|
||||
match &*meta.name() {
|
||||
"feature" => if !get(meta, &mut feature) { continue 'outer },
|
||||
"reason" => if !get(meta, &mut reason) { continue 'outer },
|
||||
"issue" => if !get(meta, &mut issue) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, meta.span,
|
||||
AttrError::UnknownMetaItem(meta.name()));
|
||||
continue 'outer
|
||||
if let Some(mi) = meta.meta_item() {
|
||||
match &*mi.name() {
|
||||
"feature" => if !get(mi, &mut feature) { continue 'outer },
|
||||
"reason" => if !get(mi, &mut reason) { continue 'outer },
|
||||
"issue" => if !get(mi, &mut issue) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, meta.span,
|
||||
AttrError::UnknownMetaItem(mi.name()));
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -645,14 +720,19 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
|
|||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
match &*meta.name() {
|
||||
"feature" => if !get(meta, &mut feature) { continue 'outer },
|
||||
"since" => if !get(meta, &mut since) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, meta.span,
|
||||
AttrError::UnknownMetaItem(meta.name()));
|
||||
continue 'outer
|
||||
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
|
||||
match &*mi.name() {
|
||||
"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()));
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -739,14 +819,19 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
|
|||
let mut since = None;
|
||||
let mut note = None;
|
||||
for meta in metas {
|
||||
match &*meta.name() {
|
||||
"since" => if !get(meta, &mut since) { continue 'outer },
|
||||
"note" => if !get(meta, &mut note) { continue 'outer },
|
||||
_ => {
|
||||
handle_errors(diagnostic, meta.span,
|
||||
AttrError::UnknownMetaItem(meta.name()));
|
||||
continue 'outer
|
||||
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
|
||||
match &*mi.name() {
|
||||
"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()));
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handle_errors(diagnostic, meta.span, AttrError::UnsupportedLiteral);
|
||||
continue 'outer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -796,32 +881,36 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
|
|||
ast::MetaItemKind::List(ref s, ref items) if s == "repr" => {
|
||||
mark_used(attr);
|
||||
for item in items {
|
||||
match item.node {
|
||||
ast::MetaItemKind::Word(ref word) => {
|
||||
let hint = match &word[..] {
|
||||
// Can't use "extern" because it's not a lexical identifier.
|
||||
"C" => Some(ReprExtern),
|
||||
"packed" => Some(ReprPacked),
|
||||
"simd" => Some(ReprSimd),
|
||||
_ => match int_type_of_word(&word) {
|
||||
Some(ity) => Some(ReprInt(item.span, ity)),
|
||||
None => {
|
||||
// Not a word we recognize
|
||||
span_err!(diagnostic, item.span, E0552,
|
||||
"unrecognized representation hint");
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
if !item.is_meta_item() {
|
||||
handle_errors(diagnostic, item.span, AttrError::UnsupportedLiteral);
|
||||
continue
|
||||
}
|
||||
|
||||
match hint {
|
||||
Some(h) => acc.push(h),
|
||||
None => { }
|
||||
if let Some(mi) = item.word() {
|
||||
let word = &*mi.name();
|
||||
let hint = match word {
|
||||
// Can't use "extern" because it's not a lexical identifier.
|
||||
"C" => Some(ReprExtern),
|
||||
"packed" => Some(ReprPacked),
|
||||
"simd" => Some(ReprSimd),
|
||||
_ => match int_type_of_word(word) {
|
||||
Some(ity) => Some(ReprInt(item.span, ity)),
|
||||
None => {
|
||||
// Not a word we recognize
|
||||
span_err!(diagnostic, item.span, E0552,
|
||||
"unrecognized representation hint");
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match hint {
|
||||
Some(h) => acc.push(h),
|
||||
None => { }
|
||||
}
|
||||
// Not a word:
|
||||
_ => span_err!(diagnostic, item.span, E0553,
|
||||
"unrecognized enum representation hint"),
|
||||
} else {
|
||||
span_err!(diagnostic, item.span, E0553,
|
||||
"unrecognized enum representation hint");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use attr::{AttrMetaMethods, HasAttrs};
|
||||
use attr::HasAttrs;
|
||||
use feature_gate::{emit_feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
|
||||
use fold::Folder;
|
||||
use {fold, attr};
|
||||
|
|
@ -52,6 +52,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) {
|
||||
(2, Some(cfg), Some(mi)) => (cfg, mi),
|
||||
_ => {
|
||||
|
|
@ -61,15 +62,24 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
if attr::cfg_matches(self.config, &cfg, self.sess, self.features) {
|
||||
self.process_cfg_attr(respan(mi.span, ast::Attribute_ {
|
||||
id: attr::mk_attr_id(),
|
||||
style: attr.node.style,
|
||||
value: mi.clone(),
|
||||
is_sugared_doc: false,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
use attr::cfg_matches;
|
||||
match (cfg.meta_item(), mi.meta_item()) {
|
||||
(Some(cfg), Some(mi)) =>
|
||||
if cfg_matches(self.config, &cfg, self.sess, self.features) {
|
||||
self.process_cfg_attr(respan(mi.span, ast::Attribute_ {
|
||||
id: attr::mk_attr_id(),
|
||||
style: attr.node.style,
|
||||
value: mi.clone(),
|
||||
is_sugared_doc: false,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
_ => {
|
||||
let msg = "unexpected literal(s) in `#[cfg_attr(<cfg pattern>, <attr>)]`";
|
||||
self.sess.span_diagnostic.span_err(attr.span, msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +101,12 @@ impl<'a> StripUnconfigured<'a> {
|
|||
return true;
|
||||
}
|
||||
|
||||
attr::cfg_matches(self.config, &mis[0], self.sess, self.features)
|
||||
if !mis[0].is_meta_item() {
|
||||
self.sess.span_diagnostic.span_err(mis[0].span, "unexpected literal");
|
||||
return true;
|
||||
}
|
||||
|
||||
attr::cfg_matches(self.config, mis[0].meta_item().unwrap(), self.sess, self.features)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +180,9 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
|
|||
ast::ItemKind::Struct(def, generics) => {
|
||||
ast::ItemKind::Struct(fold_struct(self, def), generics)
|
||||
}
|
||||
ast::ItemKind::Union(def, generics) => {
|
||||
ast::ItemKind::Union(fold_struct(self, def), generics)
|
||||
}
|
||||
ast::ItemKind::Enum(def, generics) => {
|
||||
let variants = def.variants.into_iter().filter_map(|v| {
|
||||
self.configure(v).map(|v| {
|
||||
|
|
|
|||
|
|
@ -161,6 +161,24 @@ fn main() {}
|
|||
```
|
||||
"##,
|
||||
|
||||
E0565: r##"
|
||||
A literal was used in an attribute that doesn't support literals.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0565
|
||||
#[inline("always")] // error: unsupported literal
|
||||
pub fn something() {}
|
||||
```
|
||||
|
||||
Literals in attributes are new and largely unsupported. Work to support literals
|
||||
where appropriate is ongoing. Try using an unquoted name instead:
|
||||
|
||||
```
|
||||
#[inline(always)]
|
||||
pub fn something() {}
|
||||
```
|
||||
"##,
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
|
|
|
|||
|
|
@ -60,13 +60,6 @@ impl HasAttrs for Annotatable {
|
|||
}
|
||||
|
||||
impl Annotatable {
|
||||
pub fn attrs(&self) -> &[ast::Attribute] {
|
||||
HasAttrs::attrs(self)
|
||||
}
|
||||
pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
|
||||
self.map_attrs(|_| attrs)
|
||||
}
|
||||
|
||||
pub fn expect_item(self) -> P<ast::Item> {
|
||||
match self {
|
||||
Annotatable::Item(i) => i,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use abi::Abi;
|
|||
use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
|
||||
use attr;
|
||||
use syntax_pos::{Span, DUMMY_SP, Pos};
|
||||
use codemap::{respan, Spanned};
|
||||
use codemap::{dummy_spanned, respan, Spanned};
|
||||
use ext::base::ExtCtxt;
|
||||
use parse::token::{self, keywords, InternedString};
|
||||
use ptr::P;
|
||||
|
|
@ -171,9 +171,11 @@ pub trait AstBuilder {
|
|||
span: Span,
|
||||
ident: ast::Ident,
|
||||
bm: ast::BindingMode) -> P<ast::Pat>;
|
||||
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>> ) -> P<ast::Pat>;
|
||||
fn pat_struct(&self, span: Span,
|
||||
path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>> ) -> P<ast::Pat>;
|
||||
fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat>;
|
||||
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
|
||||
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat>;
|
||||
fn pat_struct(&self, span: Span, path: ast::Path,
|
||||
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat>;
|
||||
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat>;
|
||||
|
||||
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>;
|
||||
|
|
@ -277,10 +279,13 @@ pub trait AstBuilder {
|
|||
fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute;
|
||||
|
||||
fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem>;
|
||||
|
||||
fn meta_list_item_word(&self, sp: Span, w: InternedString) -> ast::NestedMetaItem;
|
||||
|
||||
fn meta_list(&self,
|
||||
sp: Span,
|
||||
name: InternedString,
|
||||
mis: Vec<P<ast::MetaItem>> )
|
||||
mis: Vec<ast::NestedMetaItem> )
|
||||
-> P<ast::MetaItem>;
|
||||
fn meta_name_value(&self,
|
||||
sp: Span,
|
||||
|
|
@ -802,10 +807,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
let binding_expr = self.expr_ident(sp, binding_variable);
|
||||
|
||||
// Ok(__try_var) pattern
|
||||
let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat.clone()));
|
||||
let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]);
|
||||
|
||||
// Err(__try_var) (pattern and expression resp.)
|
||||
let err_pat = self.pat_enum(sp, err_path.clone(), vec!(binding_pat));
|
||||
let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]);
|
||||
let err_inner_expr = self.expr_call(sp, self.expr_path(err_path),
|
||||
vec!(binding_expr.clone()));
|
||||
// return Err(__try_var)
|
||||
|
|
@ -842,18 +847,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None);
|
||||
self.pat(span, pat)
|
||||
}
|
||||
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
let pat = if subpats.is_empty() {
|
||||
PatKind::Path(None, path)
|
||||
} else {
|
||||
PatKind::TupleStruct(path, subpats, None)
|
||||
};
|
||||
self.pat(span, pat)
|
||||
fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Path(None, path))
|
||||
}
|
||||
fn pat_struct(&self, span: Span,
|
||||
path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
|
||||
let pat = PatKind::Struct(path, field_pats, false);
|
||||
self.pat(span, pat)
|
||||
fn pat_tuple_struct(&self, span: Span, path: ast::Path,
|
||||
subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::TupleStruct(path, subpats, None))
|
||||
}
|
||||
fn pat_struct(&self, span: Span, path: ast::Path,
|
||||
field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Struct(path, field_pats, false))
|
||||
}
|
||||
fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
|
||||
self.pat(span, PatKind::Tuple(pats, None))
|
||||
|
|
@ -862,25 +865,25 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
let some = self.std_path(&["option", "Option", "Some"]);
|
||||
let path = self.path_global(span, some);
|
||||
self.pat_enum(span, path, vec!(pat))
|
||||
self.pat_tuple_struct(span, path, vec![pat])
|
||||
}
|
||||
|
||||
fn pat_none(&self, span: Span) -> P<ast::Pat> {
|
||||
let some = self.std_path(&["option", "Option", "None"]);
|
||||
let path = self.path_global(span, some);
|
||||
self.pat_enum(span, path, vec!())
|
||||
self.pat_path(span, path)
|
||||
}
|
||||
|
||||
fn pat_ok(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
let some = self.std_path(&["result", "Result", "Ok"]);
|
||||
let path = self.path_global(span, some);
|
||||
self.pat_enum(span, path, vec!(pat))
|
||||
self.pat_tuple_struct(span, path, vec![pat])
|
||||
}
|
||||
|
||||
fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
|
||||
let some = self.std_path(&["result", "Result", "Err"]);
|
||||
let path = self.path_global(span, some);
|
||||
self.pat_enum(span, path, vec!(pat))
|
||||
self.pat_tuple_struct(span, path, vec![pat])
|
||||
}
|
||||
|
||||
fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {
|
||||
|
|
@ -1016,7 +1019,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
Vec::new(),
|
||||
ast::ItemKind::Fn(self.fn_decl(inputs, output),
|
||||
ast::Unsafety::Normal,
|
||||
ast::Constness::NotConst,
|
||||
dummy_spanned(ast::Constness::NotConst),
|
||||
Abi::Rust,
|
||||
generics,
|
||||
body))
|
||||
|
|
@ -1141,10 +1144,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> {
|
||||
attr::mk_spanned_word_item(sp, w)
|
||||
}
|
||||
fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<P<ast::MetaItem>>)
|
||||
|
||||
fn meta_list_item_word(&self, sp: Span, w: InternedString) -> ast::NestedMetaItem {
|
||||
respan(sp, ast::NestedMetaItemKind::MetaItem(attr::mk_spanned_word_item(sp, w)))
|
||||
}
|
||||
|
||||
fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<ast::NestedMetaItem>)
|
||||
-> P<ast::MetaItem> {
|
||||
attr::mk_spanned_list_item(sp, name, mis)
|
||||
}
|
||||
|
||||
fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
|
||||
-> P<ast::MetaItem> {
|
||||
attr::mk_spanned_name_value_item(sp, name, respan(sp, value))
|
||||
|
|
@ -1178,7 +1187,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
fn item_use_list(&self, sp: Span, vis: ast::Visibility,
|
||||
path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item> {
|
||||
let imports = imports.iter().map(|id| {
|
||||
let item = ast::PathListItemKind::Ident {
|
||||
let item = ast::PathListItem_ {
|
||||
name: *id,
|
||||
rename: None,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use ast::{MacStmtStyle, Stmt, StmtKind, ItemKind};
|
|||
use ast;
|
||||
use ext::hygiene::Mark;
|
||||
use attr::{self, HasAttrs};
|
||||
use attr::AttrMetaMethods;
|
||||
use codemap::{dummy_spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
|
||||
use syntax_pos::{self, Span, ExpnId};
|
||||
use config::StripUnconfigured;
|
||||
|
|
|
|||
|
|
@ -26,11 +26,9 @@ use self::AttributeType::*;
|
|||
use self::AttributeGate::*;
|
||||
|
||||
use abi::Abi;
|
||||
use ast::{NodeId, PatKind};
|
||||
use ast;
|
||||
use ast::{self, NodeId, PatKind};
|
||||
use attr;
|
||||
use attr::AttrMetaMethods;
|
||||
use codemap::CodeMap;
|
||||
use codemap::{CodeMap, Spanned};
|
||||
use syntax_pos::Span;
|
||||
use errors::Handler;
|
||||
use visit::{self, FnKind, Visitor};
|
||||
|
|
@ -280,7 +278,10 @@ declare_features! (
|
|||
(active, relaxed_adts, "1.12.0", Some(35626)),
|
||||
|
||||
// The `!` type
|
||||
(active, never_type, "1.13.0", Some(35121))
|
||||
(active, never_type, "1.13.0", Some(35121)),
|
||||
|
||||
// Allows all literals in attribute lists and values of key-value pairs.
|
||||
(active, attr_literals, "1.13.0", Some(34981))
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
|
|
@ -830,11 +831,34 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn contains_novel_literal(item: &ast::MetaItem) -> bool {
|
||||
use ast::MetaItemKind::*;
|
||||
use ast::NestedMetaItemKind::*;
|
||||
|
||||
match item.node {
|
||||
Word(..) => false,
|
||||
NameValue(_, ref lit) => !lit.node.is_str(),
|
||||
List(_, ref list) => list.iter().any(|li| {
|
||||
match li.node {
|
||||
MetaItem(ref mi) => contains_novel_literal(&**mi),
|
||||
Literal(_) => true,
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
fn visit_attribute(&mut self, attr: &ast::Attribute) {
|
||||
if !self.context.cm.span_allows_unstable(attr.span) {
|
||||
// check for gated attributes
|
||||
self.context.check_attribute(attr, false);
|
||||
}
|
||||
|
||||
if contains_novel_literal(&*(attr.node.value)) {
|
||||
gate_feature_post!(&self, attr_literals, attr.span,
|
||||
"non-string literals in attributes, or string \
|
||||
literals in top-level positions, are experimental");
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_name(&mut self, sp: Span, name: ast::Name) {
|
||||
|
|
@ -894,7 +918,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
|||
for attr in &i.attrs {
|
||||
if attr.name() == "repr" {
|
||||
for item in attr.meta_item_list().unwrap_or(&[]) {
|
||||
if item.name() == "simd" {
|
||||
if item.check_name("simd") {
|
||||
gate_feature_post!(&self, repr_simd, i.span,
|
||||
"SIMD types are experimental \
|
||||
and possibly buggy");
|
||||
|
|
@ -1046,7 +1070,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
|||
_node_id: NodeId) {
|
||||
// check for const fn declarations
|
||||
match fn_kind {
|
||||
FnKind::ItemFn(_, _, _, ast::Constness::Const, _, _) => {
|
||||
FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _) => {
|
||||
gate_feature_post!(&self, const_fn, span, "const fn is unstable");
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -1078,7 +1102,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
|||
if block.is_none() {
|
||||
self.check_abi(sig.abi, ti.span);
|
||||
}
|
||||
if sig.constness == ast::Constness::Const {
|
||||
if sig.constness.node == ast::Constness::Const {
|
||||
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
|
||||
}
|
||||
}
|
||||
|
|
@ -1105,7 +1129,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
|||
"associated constants are experimental")
|
||||
}
|
||||
ast::ImplItemKind::Method(ref sig, _) => {
|
||||
if sig.constness == ast::Constness::Const {
|
||||
if sig.constness.node == ast::Constness::Const {
|
||||
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
|
||||
}
|
||||
}
|
||||
|
|
@ -1154,13 +1178,14 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
|
|||
}
|
||||
Some(list) => {
|
||||
for mi in list {
|
||||
let name = if mi.is_word() {
|
||||
mi.name()
|
||||
} else {
|
||||
span_err!(span_handler, mi.span, E0556,
|
||||
"malformed feature, expected just one word");
|
||||
continue
|
||||
};
|
||||
let name = if let Some(word) = mi.word() {
|
||||
word.name()
|
||||
} else {
|
||||
span_err!(span_handler, mi.span, E0556,
|
||||
"malformed feature, expected just one word");
|
||||
continue
|
||||
};
|
||||
|
||||
if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
|
||||
.find(|& &(n, _, _, _)| name == n) {
|
||||
*(setter(&mut features)) = true;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ pub trait Folder : Sized {
|
|||
noop_fold_meta_items(meta_items, self)
|
||||
}
|
||||
|
||||
fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
|
||||
noop_fold_meta_list_item(list_item, self)
|
||||
}
|
||||
|
||||
fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
|
||||
noop_fold_meta_item(meta_item, self)
|
||||
}
|
||||
|
|
@ -307,18 +311,10 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
|
|||
ViewPathList(fld.fold_path(path),
|
||||
path_list_idents.move_map(|path_list_ident| {
|
||||
Spanned {
|
||||
node: match path_list_ident.node {
|
||||
PathListItemKind::Ident { id, name, rename } =>
|
||||
PathListItemKind::Ident {
|
||||
id: fld.new_id(id),
|
||||
rename: rename,
|
||||
name: name
|
||||
},
|
||||
PathListItemKind::Mod { id, rename } =>
|
||||
PathListItemKind::Mod {
|
||||
id: fld.new_id(id),
|
||||
rename: rename
|
||||
}
|
||||
node: PathListItem_ {
|
||||
id: fld.new_id(path_list_ident.node.id),
|
||||
rename: path_list_ident.node.rename,
|
||||
name: path_list_ident.node.name,
|
||||
},
|
||||
span: fld.new_span(path_list_ident.span)
|
||||
}
|
||||
|
|
@ -513,12 +509,25 @@ pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_meta_list_item<T: Folder>(li: NestedMetaItem, fld: &mut T)
|
||||
-> NestedMetaItem {
|
||||
Spanned {
|
||||
node: match li.node {
|
||||
NestedMetaItemKind::MetaItem(mi) => {
|
||||
NestedMetaItemKind::MetaItem(fld.fold_meta_item(mi))
|
||||
},
|
||||
NestedMetaItemKind::Literal(lit) => NestedMetaItemKind::Literal(lit)
|
||||
},
|
||||
span: fld.new_span(li.span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
|
||||
mi.map(|Spanned {node, span}| Spanned {
|
||||
node: match node {
|
||||
MetaItemKind::Word(id) => MetaItemKind::Word(id),
|
||||
MetaItemKind::List(id, mis) => {
|
||||
MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_item(e)))
|
||||
MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_list_item(e)))
|
||||
}
|
||||
MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s)
|
||||
},
|
||||
|
|
@ -698,12 +707,13 @@ pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
|
|||
o_lt.map(|lt| fld.fold_lifetime(lt))
|
||||
}
|
||||
|
||||
pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause}: Generics,
|
||||
pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause, span}: Generics,
|
||||
fld: &mut T) -> Generics {
|
||||
Generics {
|
||||
ty_params: fld.fold_ty_params(ty_params),
|
||||
lifetimes: fld.fold_lifetime_defs(lifetimes),
|
||||
where_clause: fld.fold_where_clause(where_clause),
|
||||
span: fld.new_span(span),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -875,6 +885,10 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
|
|||
let struct_def = folder.fold_variant_data(struct_def);
|
||||
ItemKind::Struct(struct_def, folder.fold_generics(generics))
|
||||
}
|
||||
ItemKind::Union(struct_def, generics) => {
|
||||
let struct_def = folder.fold_variant_data(struct_def);
|
||||
ItemKind::Union(struct_def, folder.fold_generics(generics))
|
||||
}
|
||||
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
||||
ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,9 +193,26 @@ impl<'a> Parser<'a> {
|
|||
Ok(attrs)
|
||||
}
|
||||
|
||||
/// matches meta_item = IDENT
|
||||
/// | IDENT = lit
|
||||
/// | IDENT meta_seq
|
||||
fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
|
||||
let lit = self.parse_lit()?;
|
||||
debug!("Checking if {:?} is unusuffixed.", lit);
|
||||
|
||||
if !lit.node.is_unsuffixed() {
|
||||
let msg = "suffixed literals are not allowed in attributes";
|
||||
self.diagnostic().struct_span_err(lit.span, msg)
|
||||
.help("instead of using a suffixed literal \
|
||||
(1u8, 1.0f32, etc.), use an unsuffixed version \
|
||||
(1, 1.0, etc.).")
|
||||
.emit()
|
||||
}
|
||||
|
||||
Ok(lit)
|
||||
}
|
||||
|
||||
/// Per RFC#1559, matches the following grammar:
|
||||
///
|
||||
/// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
|
||||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||
pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
|
||||
let nt_meta = match self.token {
|
||||
token::Interpolated(token::NtMeta(ref e)) => Some(e.clone()),
|
||||
|
|
@ -213,16 +230,7 @@ impl<'a> Parser<'a> {
|
|||
match self.token {
|
||||
token::Eq => {
|
||||
self.bump();
|
||||
let lit = self.parse_lit()?;
|
||||
// FIXME #623 Non-string meta items are not serialized correctly;
|
||||
// just forbid them for now
|
||||
match lit.node {
|
||||
ast::LitKind::Str(..) => {}
|
||||
_ => {
|
||||
self.span_err(lit.span,
|
||||
"non-string literals are not allowed in meta-items");
|
||||
}
|
||||
}
|
||||
let lit = self.parse_unsuffixed_lit()?;
|
||||
let hi = self.span.hi;
|
||||
Ok(P(spanned(lo, hi, ast::MetaItemKind::NameValue(name, lit))))
|
||||
}
|
||||
|
|
@ -238,11 +246,35 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// matches meta_seq = ( COMMASEP(meta_item) )
|
||||
fn parse_meta_seq(&mut self) -> PResult<'a, Vec<P<ast::MetaItem>>> {
|
||||
/// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
|
||||
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
||||
let sp = self.span;
|
||||
let lo = self.span.lo;
|
||||
|
||||
match self.parse_unsuffixed_lit() {
|
||||
Ok(lit) => {
|
||||
return Ok(spanned(lo, self.span.hi, ast::NestedMetaItemKind::Literal(lit)))
|
||||
}
|
||||
Err(ref mut err) => self.diagnostic().cancel(err)
|
||||
}
|
||||
|
||||
match self.parse_meta_item() {
|
||||
Ok(mi) => {
|
||||
return Ok(spanned(lo, self.span.hi, ast::NestedMetaItemKind::MetaItem(mi)))
|
||||
}
|
||||
Err(ref mut err) => self.diagnostic().cancel(err)
|
||||
}
|
||||
|
||||
let found = self.this_token_to_string();
|
||||
let msg = format!("expected unsuffixed literal or identifier, found {}", found);
|
||||
Err(self.diagnostic().struct_span_err(sp, &msg))
|
||||
}
|
||||
|
||||
/// matches meta_seq = ( COMMASEP(meta_item_inner) )
|
||||
fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
|
||||
self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
|
||||
&token::CloseDelim(token::Paren),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p: &mut Parser<'a>| p.parse_meta_item())
|
||||
|p: &mut Parser<'a>| p.parse_meta_item_inner())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -674,11 +674,11 @@ pub fn integer_lit(s: &str,
|
|||
mod tests {
|
||||
use super::*;
|
||||
use std::rc::Rc;
|
||||
use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION};
|
||||
use syntax_pos::{self, Span, BytePos, Pos, NO_EXPANSION};
|
||||
use codemap::Spanned;
|
||||
use ast::{self, PatKind};
|
||||
use abi::Abi;
|
||||
use attr::{first_attr_value_str_by_name, AttrMetaMethods};
|
||||
use attr::first_attr_value_str_by_name;
|
||||
use parse;
|
||||
use parse::parser::Parser;
|
||||
use parse::token::{str_to_ident};
|
||||
|
|
@ -937,7 +937,10 @@ mod tests {
|
|||
variadic: false
|
||||
}),
|
||||
ast::Unsafety::Normal,
|
||||
ast::Constness::NotConst,
|
||||
Spanned {
|
||||
span: sp(0,2),
|
||||
node: ast::Constness::NotConst,
|
||||
},
|
||||
Abi::Rust,
|
||||
ast::Generics{ // no idea on either of these:
|
||||
lifetimes: Vec::new(),
|
||||
|
|
@ -945,7 +948,8 @@ mod tests {
|
|||
where_clause: ast::WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
}
|
||||
},
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
},
|
||||
P(ast::Block {
|
||||
stmts: vec!(ast::Stmt {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
|||
use ast::{Visibility, WhereClause};
|
||||
use ast::{BinOpKind, UnOp};
|
||||
use ast;
|
||||
use codemap::{self, CodeMap, Spanned, spanned};
|
||||
use codemap::{self, CodeMap, Spanned, spanned, respan};
|
||||
use syntax_pos::{self, Span, BytePos, mk_sp};
|
||||
use errors::{self, DiagnosticBuilder};
|
||||
use ext::tt::macro_parser;
|
||||
|
|
@ -725,8 +725,8 @@ impl<'a> Parser<'a> {
|
|||
let gt_str = Parser::token_to_string(&token::Gt);
|
||||
let this_token_str = self.this_token_to_string();
|
||||
Err(self.fatal(&format!("expected `{}`, found `{}`",
|
||||
gt_str,
|
||||
this_token_str)))
|
||||
gt_str,
|
||||
this_token_str)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4293,6 +4293,7 @@ impl<'a> Parser<'a> {
|
|||
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
|
||||
pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
|
||||
maybe_whole!(self, NtGenerics);
|
||||
let span_lo = self.span.lo;
|
||||
|
||||
if self.eat(&token::Lt) {
|
||||
let lifetime_defs = self.parse_lifetime_defs()?;
|
||||
|
|
@ -4315,7 +4316,8 @@ impl<'a> Parser<'a> {
|
|||
where_clause: WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
}
|
||||
},
|
||||
span: mk_sp(span_lo, self.last_span.hi),
|
||||
})
|
||||
} else {
|
||||
Ok(ast::Generics::default())
|
||||
|
|
@ -4768,7 +4770,7 @@ impl<'a> Parser<'a> {
|
|||
/// Parse an item-position function declaration.
|
||||
fn parse_item_fn(&mut self,
|
||||
unsafety: Unsafety,
|
||||
constness: Constness,
|
||||
constness: Spanned<Constness>,
|
||||
abi: abi::Abi)
|
||||
-> PResult<'a, ItemInfo> {
|
||||
let (ident, mut generics) = self.parse_fn_header()?;
|
||||
|
|
@ -4794,18 +4796,21 @@ impl<'a> Parser<'a> {
|
|||
/// - `extern fn`
|
||||
/// - etc
|
||||
pub fn parse_fn_front_matter(&mut self)
|
||||
-> PResult<'a, (ast::Constness, ast::Unsafety, abi::Abi)> {
|
||||
-> PResult<'a, (Spanned<ast::Constness>,
|
||||
ast::Unsafety,
|
||||
abi::Abi)> {
|
||||
let is_const_fn = self.eat_keyword(keywords::Const);
|
||||
let const_span = self.last_span;
|
||||
let unsafety = self.parse_unsafety()?;
|
||||
let (constness, unsafety, abi) = if is_const_fn {
|
||||
(Constness::Const, unsafety, Abi::Rust)
|
||||
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
|
||||
} else {
|
||||
let abi = if self.eat_keyword(keywords::Extern) {
|
||||
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
||||
} else {
|
||||
Abi::Rust
|
||||
};
|
||||
(Constness::NotConst, unsafety, abi)
|
||||
(respan(self.last_span, Constness::NotConst), unsafety, abi)
|
||||
};
|
||||
self.expect_keyword(keywords::Fn)?;
|
||||
Ok((constness, unsafety, abi))
|
||||
|
|
@ -5704,9 +5709,12 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if self.eat_keyword(keywords::Fn) {
|
||||
// EXTERN FUNCTION ITEM
|
||||
let fn_span = self.last_span;
|
||||
let abi = opt_abi.unwrap_or(Abi::C);
|
||||
let (ident, item_, extra_attrs) =
|
||||
self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi)?;
|
||||
self.parse_item_fn(Unsafety::Normal,
|
||||
respan(fn_span, Constness::NotConst),
|
||||
abi)?;
|
||||
let last_span = self.last_span;
|
||||
let item = self.mk_item(lo,
|
||||
last_span.hi,
|
||||
|
|
@ -5740,6 +5748,7 @@ impl<'a> Parser<'a> {
|
|||
return Ok(Some(item));
|
||||
}
|
||||
if self.eat_keyword(keywords::Const) {
|
||||
let const_span = self.last_span;
|
||||
if self.check_keyword(keywords::Fn)
|
||||
|| (self.check_keyword(keywords::Unsafe)
|
||||
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
|
||||
|
|
@ -5751,7 +5760,9 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
self.bump();
|
||||
let (ident, item_, extra_attrs) =
|
||||
self.parse_item_fn(unsafety, Constness::Const, Abi::Rust)?;
|
||||
self.parse_item_fn(unsafety,
|
||||
respan(const_span, Constness::Const),
|
||||
Abi::Rust)?;
|
||||
let last_span = self.last_span;
|
||||
let item = self.mk_item(lo,
|
||||
last_span.hi,
|
||||
|
|
@ -5815,8 +5826,11 @@ impl<'a> Parser<'a> {
|
|||
if self.check_keyword(keywords::Fn) {
|
||||
// FUNCTION ITEM
|
||||
self.bump();
|
||||
let fn_span = self.last_span;
|
||||
let (ident, item_, extra_attrs) =
|
||||
self.parse_item_fn(Unsafety::Normal, Constness::NotConst, Abi::Rust)?;
|
||||
self.parse_item_fn(Unsafety::Normal,
|
||||
respan(fn_span, Constness::NotConst),
|
||||
Abi::Rust)?;
|
||||
let last_span = self.last_span;
|
||||
let item = self.mk_item(lo,
|
||||
last_span.hi,
|
||||
|
|
@ -5836,8 +5850,11 @@ impl<'a> Parser<'a> {
|
|||
Abi::Rust
|
||||
};
|
||||
self.expect_keyword(keywords::Fn)?;
|
||||
let fn_span = self.last_span;
|
||||
let (ident, item_, extra_attrs) =
|
||||
self.parse_item_fn(Unsafety::Unsafe, Constness::NotConst, abi)?;
|
||||
self.parse_item_fn(Unsafety::Unsafe,
|
||||
respan(fn_span, Constness::NotConst),
|
||||
abi)?;
|
||||
let last_span = self.last_span;
|
||||
let item = self.mk_item(lo,
|
||||
last_span.hi,
|
||||
|
|
@ -6038,13 +6055,16 @@ impl<'a> Parser<'a> {
|
|||
&token::CloseDelim(token::Brace),
|
||||
SeqSep::trailing_allowed(token::Comma), |this| {
|
||||
let lo = this.span.lo;
|
||||
let node = if this.eat_keyword(keywords::SelfValue) {
|
||||
let rename = this.parse_rename()?;
|
||||
ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename }
|
||||
let ident = if this.eat_keyword(keywords::SelfValue) {
|
||||
keywords::SelfValue.ident()
|
||||
} else {
|
||||
let ident = this.parse_ident()?;
|
||||
let rename = this.parse_rename()?;
|
||||
ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
|
||||
this.parse_ident()?
|
||||
};
|
||||
let rename = this.parse_rename()?;
|
||||
let node = ast::PathListItem_ {
|
||||
name: ident,
|
||||
rename: rename,
|
||||
id: ast::DUMMY_NODE_ID
|
||||
};
|
||||
let hi = this.last_span.hi;
|
||||
Ok(spanned(lo, hi, node))
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
|||
use ast::Attribute;
|
||||
use util::parser::AssocOp;
|
||||
use attr;
|
||||
use attr::{AttrMetaMethods, AttributeMethods};
|
||||
use codemap::{self, CodeMap};
|
||||
use syntax_pos::{self, BytePos};
|
||||
use errors;
|
||||
|
|
@ -120,7 +119,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
|
|||
// of the feature gate, so we fake them up here.
|
||||
|
||||
// #![feature(prelude_import)]
|
||||
let prelude_import_meta = attr::mk_word_item(InternedString::new("prelude_import"));
|
||||
let prelude_import_meta = attr::mk_list_word_item(InternedString::new("prelude_import"));
|
||||
let list = attr::mk_list_item(InternedString::new("feature"),
|
||||
vec![prelude_import_meta]);
|
||||
let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list);
|
||||
|
|
@ -406,6 +405,10 @@ pub fn block_to_string(blk: &ast::Block) -> String {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String {
|
||||
to_string(|s| s.print_meta_list_item(li))
|
||||
}
|
||||
|
||||
pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
|
||||
to_string(|s| s.print_meta_item(mi))
|
||||
}
|
||||
|
|
@ -764,6 +767,17 @@ pub trait PrintState<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> {
|
||||
match item.node {
|
||||
ast::NestedMetaItemKind::MetaItem(ref mi) => {
|
||||
self.print_meta_item(mi)
|
||||
},
|
||||
ast::NestedMetaItemKind::Literal(ref lit) => {
|
||||
self.print_literal(lit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
|
||||
try!(self.ibox(INDENT_UNIT));
|
||||
match item.node {
|
||||
|
|
@ -780,7 +794,7 @@ pub trait PrintState<'a> {
|
|||
try!(self.popen());
|
||||
try!(self.commasep(Consistent,
|
||||
&items[..],
|
||||
|s, i| s.print_meta_item(&i)));
|
||||
|s, i| s.print_meta_list_item(&i)));
|
||||
try!(self.pclose());
|
||||
}
|
||||
}
|
||||
|
|
@ -1001,6 +1015,7 @@ impl<'a> State<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
},
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
try!(self.print_ty_fn(f.abi,
|
||||
f.unsafety,
|
||||
|
|
@ -1184,7 +1199,7 @@ impl<'a> State<'a> {
|
|||
try!(self.print_fn(
|
||||
decl,
|
||||
unsafety,
|
||||
constness,
|
||||
constness.node,
|
||||
abi,
|
||||
Some(item.ident),
|
||||
typarams,
|
||||
|
|
@ -1236,7 +1251,10 @@ impl<'a> State<'a> {
|
|||
try!(self.head(&visibility_qualified(&item.vis, "struct")));
|
||||
try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
|
||||
}
|
||||
|
||||
ast::ItemKind::Union(ref struct_def, ref generics) => {
|
||||
try!(self.head(&visibility_qualified(&item.vis, "union")));
|
||||
try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
|
||||
}
|
||||
ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
||||
try!(self.head(""));
|
||||
try!(self.print_visibility(&item.vis));
|
||||
|
|
@ -1518,7 +1536,7 @@ impl<'a> State<'a> {
|
|||
-> io::Result<()> {
|
||||
self.print_fn(&m.decl,
|
||||
m.unsafety,
|
||||
m.constness,
|
||||
m.constness.node,
|
||||
m.abi,
|
||||
Some(ident),
|
||||
&m.generics,
|
||||
|
|
@ -2878,26 +2896,13 @@ impl<'a> State<'a> {
|
|||
try!(word(&mut self.s, "::{"));
|
||||
}
|
||||
try!(self.commasep(Inconsistent, &idents[..], |s, w| {
|
||||
match w.node {
|
||||
ast::PathListItemKind::Ident { name, rename, .. } => {
|
||||
try!(s.print_ident(name));
|
||||
if let Some(ident) = rename {
|
||||
try!(space(&mut s.s));
|
||||
try!(s.word_space("as"));
|
||||
try!(s.print_ident(ident));
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
ast::PathListItemKind::Mod { rename, .. } => {
|
||||
try!(word(&mut s.s, "self"));
|
||||
if let Some(ident) = rename {
|
||||
try!(space(&mut s.s));
|
||||
try!(s.word_space("as"));
|
||||
try!(s.print_ident(ident));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
try!(s.print_ident(w.node.name));
|
||||
if let Some(ident) = w.node.rename {
|
||||
try!(space(&mut s.s));
|
||||
try!(s.word_space("as"));
|
||||
try!(s.print_ident(ident));
|
||||
}
|
||||
Ok(())
|
||||
}));
|
||||
word(&mut self.s, "}")
|
||||
}
|
||||
|
|
@ -2982,6 +2987,7 @@ impl<'a> State<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
},
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
try!(self.print_fn(decl,
|
||||
unsafety,
|
||||
|
|
|
|||
|
|
@ -19,12 +19,11 @@ use std::iter;
|
|||
use std::slice;
|
||||
use std::mem;
|
||||
use std::vec;
|
||||
use attr::AttrMetaMethods;
|
||||
use attr;
|
||||
use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
|
||||
use std::rc::Rc;
|
||||
|
||||
use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute};
|
||||
use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned};
|
||||
use errors;
|
||||
use errors::snippet::{SnippetData};
|
||||
use config;
|
||||
|
|
@ -210,9 +209,8 @@ impl fold::Folder for EntryPointCleaner {
|
|||
folded.map(|ast::Item {id, ident, attrs, node, vis, span}| {
|
||||
let allow_str = InternedString::new("allow");
|
||||
let dead_code_str = InternedString::new("dead_code");
|
||||
let allow_dead_code_item =
|
||||
attr::mk_list_item(allow_str,
|
||||
vec![attr::mk_word_item(dead_code_str)]);
|
||||
let word_vec = vec![attr::mk_list_word_item(dead_code_str)];
|
||||
let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec);
|
||||
let allow_dead_code = attr::mk_attr_outer(attr::mk_attr_id(),
|
||||
allow_dead_code_item);
|
||||
|
||||
|
|
@ -413,6 +411,7 @@ fn should_panic(i: &ast::Item) -> ShouldPanic {
|
|||
Some(attr) => {
|
||||
let msg = attr.meta_item_list()
|
||||
.and_then(|list| list.iter().find(|mi| mi.check_name("expected")))
|
||||
.and_then(|li| li.meta_item())
|
||||
.and_then(|mi| mi.value_str());
|
||||
ShouldPanic::Yes(msg)
|
||||
}
|
||||
|
|
@ -485,7 +484,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
|
|||
let main_body = ecx.block(sp, vec![call_test_main]);
|
||||
let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty),
|
||||
ast::Unsafety::Normal,
|
||||
ast::Constness::NotConst,
|
||||
dummy_spanned(ast::Constness::NotConst),
|
||||
::abi::Abi::Rust, ast::Generics::default(), main_body);
|
||||
let main = P(ast::Item {
|
||||
ident: token::str_to_ident("main"),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ use codemap::Spanned;
|
|||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum FnKind<'a> {
|
||||
/// fn foo() or extern "Abi" fn foo()
|
||||
ItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, &'a Visibility),
|
||||
ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility),
|
||||
|
||||
/// fn foo(&self)
|
||||
Method(Ident, &'a MethodSig, Option<&'a Visibility>),
|
||||
|
|
@ -278,7 +278,8 @@ pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
|
|||
visitor.visit_ty(typ);
|
||||
walk_list!(visitor, visit_impl_item, impl_items);
|
||||
}
|
||||
ItemKind::Struct(ref struct_definition, ref generics) => {
|
||||
ItemKind::Struct(ref struct_definition, ref generics) |
|
||||
ItemKind::Union(ref struct_definition, ref generics) => {
|
||||
visitor.visit_generics(generics);
|
||||
visitor.visit_variant_data(struct_definition, item.ident,
|
||||
generics, item.id, item.span);
|
||||
|
|
@ -367,8 +368,8 @@ pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
|
|||
}
|
||||
|
||||
pub fn walk_path_list_item<V: Visitor>(visitor: &mut V, _prefix: &Path, item: &PathListItem) {
|
||||
walk_opt_ident(visitor, item.span, item.node.name());
|
||||
walk_opt_ident(visitor, item.span, item.node.rename());
|
||||
visitor.visit_ident(item.span, item.node.name);
|
||||
walk_opt_ident(visitor, item.span, item.node.rename);
|
||||
}
|
||||
|
||||
pub fn walk_path_segment<V: Visitor>(visitor: &mut V, path_span: Span, segment: &PathSegment) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: true,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
|||
additional_bounds: bounds,
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "clone",
|
||||
generics: LifetimeBounds::empty(),
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
|||
}
|
||||
|
||||
let inline = cx.meta_word(span, InternedString::new("inline"));
|
||||
let hidden = cx.meta_word(span, InternedString::new("hidden"));
|
||||
let hidden = cx.meta_list_item_word(span, InternedString::new("hidden"));
|
||||
let doc = cx.meta_list(span, InternedString::new("doc"), vec![hidden]);
|
||||
let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)];
|
||||
let trait_def = TraitDef {
|
||||
|
|
@ -50,6 +50,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "assert_receiver_is_total_eq",
|
||||
generics: LifetimeBounds::empty(),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "cmp",
|
||||
generics: LifetimeBounds::empty(),
|
||||
|
|
@ -104,7 +105,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
|
|||
};
|
||||
|
||||
let eq_arm = cx.arm(span,
|
||||
vec![cx.pat_enum(span, equals_path.clone(), vec![])],
|
||||
vec![cx.pat_path(span, equals_path.clone())],
|
||||
old);
|
||||
let neq_arm = cx.arm(span,
|
||||
vec![cx.pat_ident(span, test_id)],
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: methods,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
|
|||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: methods,
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
|
@ -165,7 +166,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
|
|||
};
|
||||
|
||||
let eq_arm = cx.arm(span,
|
||||
vec![cx.pat_some(span, cx.pat_enum(span, ordering.clone(), vec![]))],
|
||||
vec![cx.pat_some(span, cx.pat_path(span, ordering.clone()))],
|
||||
old);
|
||||
let neq_arm = cx.arm(span,
|
||||
vec![cx.pat_ident(span, test_id)],
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "fmt",
|
||||
generics: LifetimeBounds::empty(),
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "decode",
|
||||
generics: LifetimeBounds {
|
||||
|
|
@ -110,7 +111,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
|
|||
return match *substr.fields {
|
||||
StaticStruct(_, ref summary) => {
|
||||
let nfields = match *summary {
|
||||
Unnamed(ref fields) => fields.len(),
|
||||
Unnamed(ref fields, _) => fields.len(),
|
||||
Named(ref fields) => fields.len(),
|
||||
};
|
||||
let read_struct_field = cx.ident_of("read_struct_field");
|
||||
|
|
@ -193,9 +194,9 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
|
|||
where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P<Expr>
|
||||
{
|
||||
match *fields {
|
||||
Unnamed(ref fields) => {
|
||||
Unnamed(ref fields, is_tuple) => {
|
||||
let path_expr = cx.expr_path(outer_pat_path);
|
||||
if fields.is_empty() {
|
||||
if !is_tuple {
|
||||
path_expr
|
||||
} else {
|
||||
let fields = fields.iter()
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "default",
|
||||
generics: LifetimeBounds::empty(),
|
||||
|
|
@ -57,8 +58,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
|
|||
return match *substr.fields {
|
||||
StaticStruct(_, ref summary) => {
|
||||
match *summary {
|
||||
Unnamed(ref fields) => {
|
||||
if fields.is_empty() {
|
||||
Unnamed(ref fields, is_tuple) => {
|
||||
if !is_tuple {
|
||||
cx.expr_ident(trait_span, substr.type_ident)
|
||||
} else {
|
||||
let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec!(
|
||||
MethodDef {
|
||||
name: "encode",
|
||||
|
|
|
|||
|
|
@ -194,10 +194,9 @@ use std::vec;
|
|||
use syntax::abi::Abi;
|
||||
use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData};
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::codemap::{self, respan};
|
||||
use syntax::codemap::{self, dummy_spanned, respan};
|
||||
use syntax::util::move_map::MoveMap;
|
||||
use syntax::parse::token::{InternedString, keywords};
|
||||
use syntax::ptr::P;
|
||||
|
|
@ -229,6 +228,9 @@ pub struct TraitDef<'a> {
|
|||
/// Is it an `unsafe` trait?
|
||||
pub is_unsafe: bool,
|
||||
|
||||
/// Can this trait be derived for unions?
|
||||
pub supports_unions: bool,
|
||||
|
||||
pub methods: Vec<MethodDef<'a>>,
|
||||
|
||||
pub associated_types: Vec<(ast::Ident, Ty<'a>)>,
|
||||
|
|
@ -294,8 +296,8 @@ pub struct FieldInfo<'a> {
|
|||
|
||||
/// Fields for a static method
|
||||
pub enum StaticFields {
|
||||
/// Tuple structs/enum variants like this.
|
||||
Unnamed(Vec<Span>),
|
||||
/// Tuple and unit structs/enum variants like this.
|
||||
Unnamed(Vec<Span>, bool /*is tuple*/),
|
||||
/// Normal structs/struct variants.
|
||||
Named(Vec<(Ident, Span)>),
|
||||
}
|
||||
|
|
@ -488,7 +490,7 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
});
|
||||
|
||||
let Generics { mut lifetimes, ty_params, mut where_clause } = self.generics
|
||||
let Generics { mut lifetimes, ty_params, mut where_clause, span } = self.generics
|
||||
.to_generics(cx, self.span, type_ident, generics);
|
||||
let mut ty_params = ty_params.into_vec();
|
||||
|
||||
|
|
@ -590,6 +592,7 @@ impl<'a> TraitDef<'a> {
|
|||
lifetimes: lifetimes,
|
||||
ty_params: P::from_vec(ty_params),
|
||||
where_clause: where_clause,
|
||||
span: span,
|
||||
};
|
||||
|
||||
// Create the reference to the trait.
|
||||
|
|
@ -623,7 +626,7 @@ impl<'a> TraitDef<'a> {
|
|||
let unused_qual = cx.attribute(self.span,
|
||||
cx.meta_list(self.span,
|
||||
InternedString::new("allow"),
|
||||
vec![cx.meta_word(self.span,
|
||||
vec![cx.meta_list_item_word(self.span,
|
||||
InternedString::new("unused_qualifications"))]));
|
||||
let mut a = vec![attr, unused_qual];
|
||||
a.extend(self.attributes.iter().cloned());
|
||||
|
|
@ -901,7 +904,8 @@ impl<'a> MethodDef<'a> {
|
|||
generics: fn_generics,
|
||||
abi: abi,
|
||||
unsafety: unsafety,
|
||||
constness: ast::Constness::NotConst,
|
||||
constness:
|
||||
dummy_spanned(ast::Constness::NotConst),
|
||||
decl: fn_decl,
|
||||
},
|
||||
body_block),
|
||||
|
|
@ -1470,7 +1474,7 @@ impl<'a> TraitDef<'a> {
|
|||
(_, false) => Named(named_idents),
|
||||
// empty structs
|
||||
_ if struct_def.is_struct() => Named(named_idents),
|
||||
_ => Unnamed(just_spans),
|
||||
_ => Unnamed(just_spans, struct_def.is_tuple()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1510,26 +1514,32 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
|
||||
let subpats = self.create_subpatterns(cx, paths, mutbl);
|
||||
let pattern = if struct_def.is_struct() {
|
||||
let field_pats = subpats.into_iter()
|
||||
.zip(&ident_exprs)
|
||||
.map(|(pat, &(sp, ident, _, _))| {
|
||||
if ident.is_none() {
|
||||
cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
|
||||
}
|
||||
codemap::Spanned {
|
||||
span: pat.span,
|
||||
node: ast::FieldPat {
|
||||
ident: ident.unwrap(),
|
||||
pat: pat,
|
||||
is_shorthand: false,
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
cx.pat_struct(self.span, struct_path, field_pats)
|
||||
} else {
|
||||
cx.pat_enum(self.span, struct_path, subpats)
|
||||
let pattern = match *struct_def {
|
||||
VariantData::Struct(..) => {
|
||||
let field_pats = subpats.into_iter()
|
||||
.zip(&ident_exprs)
|
||||
.map(|(pat, &(sp, ident, _, _))| {
|
||||
if ident.is_none() {
|
||||
cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
|
||||
}
|
||||
codemap::Spanned {
|
||||
span: pat.span,
|
||||
node: ast::FieldPat {
|
||||
ident: ident.unwrap(),
|
||||
pat: pat,
|
||||
is_shorthand: false,
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
cx.pat_struct(self.span, struct_path, field_pats)
|
||||
}
|
||||
VariantData::Tuple(..) => {
|
||||
cx.pat_tuple_struct(self.span, struct_path, subpats)
|
||||
}
|
||||
VariantData::Unit(..) => {
|
||||
cx.pat_path(self.span, struct_path)
|
||||
}
|
||||
};
|
||||
|
||||
(pattern, ident_exprs)
|
||||
|
|
|
|||
|
|
@ -207,7 +207,8 @@ fn mk_ty_param(cx: &ExtCtxt,
|
|||
cx.typaram(span, cx.ident_of(name), bounds, None)
|
||||
}
|
||||
|
||||
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>) -> Generics {
|
||||
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, span: Span)
|
||||
-> Generics {
|
||||
Generics {
|
||||
lifetimes: lifetimes,
|
||||
ty_params: P::from_vec(ty_params),
|
||||
|
|
@ -215,6 +216,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>) -
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
},
|
||||
span: span,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +259,7 @@ impl<'a> LifetimeBounds<'a> {
|
|||
}
|
||||
})
|
||||
.collect();
|
||||
mk_generics(lifetimes, ty_params)
|
||||
mk_generics(lifetimes, ty_params, span)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
|||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: "hash",
|
||||
generics: LifetimeBounds {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
//! The compiler code necessary to implement the `#[derive]` extensions.
|
||||
|
||||
use syntax::ast::{self, MetaItem};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
|
||||
use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
|
|
@ -98,8 +97,8 @@ fn expand_derive(cx: &mut ExtCtxt,
|
|||
let mut eq_span = None;
|
||||
|
||||
for titem in traits.iter().rev() {
|
||||
let tname = if titem.is_word() {
|
||||
titem.name()
|
||||
let tname = if let Some(word) = titem.word() {
|
||||
word.name()
|
||||
} else {
|
||||
cx.span_err(titem.span, "malformed `derive` entry");
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ extern crate syntax_pos;
|
|||
extern crate rustc;
|
||||
extern crate rustc_plugin;
|
||||
|
||||
use syntax::ast::{self, Item, MetaItem, ImplItem, TraitItem, ItemKind};
|
||||
use syntax::ast::{self, Item, MetaItem, ItemKind};
|
||||
use syntax::ext::base::*;
|
||||
use syntax::parse::{self, token};
|
||||
use syntax::ptr::P;
|
||||
|
|
@ -62,8 +62,8 @@ fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree])
|
|||
}
|
||||
|
||||
fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
attr: &MetaItem,
|
||||
_sp: Span,
|
||||
_attr: &MetaItem,
|
||||
it: Annotatable) -> Annotatable {
|
||||
match it {
|
||||
Annotatable::Item(it) => {
|
||||
|
|
@ -72,7 +72,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone()
|
||||
}))
|
||||
}
|
||||
Annotatable::ImplItem(it) => {
|
||||
Annotatable::ImplItem(_) => {
|
||||
quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| {
|
||||
match i.node {
|
||||
ItemKind::Impl(_, _, _, _, _, mut items) => {
|
||||
|
|
@ -82,7 +82,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
}
|
||||
})
|
||||
}
|
||||
Annotatable::TraitItem(it) => {
|
||||
Annotatable::TraitItem(_) => {
|
||||
quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| {
|
||||
match i.node {
|
||||
ItemKind::Trait(_, _, _, mut items) => {
|
||||
|
|
@ -97,15 +97,15 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
|
||||
// Create a duplicate of the annotatable, based on the MetaItem
|
||||
fn expand_duplicate(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
_sp: Span,
|
||||
mi: &MetaItem,
|
||||
it: &Annotatable,
|
||||
push: &mut FnMut(Annotatable))
|
||||
{
|
||||
let copy_name = match mi.node {
|
||||
ast::MetaItemKind::List(_, ref xs) => {
|
||||
if let ast::MetaItemKind::Word(ref w) = xs[0].node {
|
||||
token::str_to_ident(&w)
|
||||
if let Some(word) = xs[0].word() {
|
||||
token::str_to_ident(&word.name())
|
||||
} else {
|
||||
cx.span_err(mi.span, "Expected word");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn f<T>() {} //~ ERROR E0132
|
||||
fn f< T >() {} //~ ERROR E0132
|
||||
//~| NOTE start function cannot have type parameters
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
17
src/test/compile-fail/E0565-1.rs
Normal file
17
src/test/compile-fail/E0565-1.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(attr_literals)]
|
||||
|
||||
// deprecated doesn't currently support literals
|
||||
#[deprecated("since")] //~ ERROR E0565
|
||||
fn f() { }
|
||||
|
||||
fn main() { }
|
||||
17
src/test/compile-fail/E0565.rs
Normal file
17
src/test/compile-fail/E0565.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(attr_literals)]
|
||||
|
||||
// repr currently doesn't support literals
|
||||
#[repr("C")] //~ ERROR E0565
|
||||
struct A { }
|
||||
|
||||
fn main() { }
|
||||
33
src/test/compile-fail/attr-literals.rs
Normal file
33
src/test/compile-fail/attr-literals.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that literals in attributes parse just fine.
|
||||
|
||||
#![feature(rustc_attrs, attr_literals)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
|
||||
struct Q { }
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { }
|
||||
|
|
@ -21,7 +21,7 @@ trait Foo {
|
|||
|
||||
impl Foo for u32 {
|
||||
const fn f() -> u32 { 22 }
|
||||
//~^ ERROR E0379
|
||||
//~^ ERROR trait fns cannot be declared const
|
||||
//~| NOTE trait fns cannot be const
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,12 @@
|
|||
#![feature(const_fn)]
|
||||
|
||||
trait Foo {
|
||||
const fn f() -> u32; //~ ERROR trait fns cannot be declared const
|
||||
const fn g() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
|
||||
const fn f() -> u32;
|
||||
//~^ ERROR trait fns cannot be declared const
|
||||
//~| NOTE trait fns cannot be const
|
||||
const fn g() -> u32 { 0 }
|
||||
//~^ ERROR trait fns cannot be declared const
|
||||
//~| NOTE trait fns cannot be const
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
44
src/test/compile-fail/gated-attr-literals.rs
Normal file
44
src/test/compile-fail/gated-attr-literals.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that literals in attributes don't parse without the feature gate.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR string literals in top-level positions, are experimental
|
||||
#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
||||
#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
||||
#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR non-string literals in attributes
|
||||
#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
|
||||
//~^ ERROR string literals in top-level positions, are experimental
|
||||
#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
|
||||
//~^ ERROR string literals in top-level positions, are experimental
|
||||
struct Q { }
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { }
|
||||
25
src/test/parse-fail/suffixed-literal-meta.rs
Normal file
25
src/test/parse-fail/suffixed-literal-meta.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
#[foo = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
#[foo = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
|
||||
fn main() { }
|
||||
|
|
@ -8,10 +8,16 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// pp-exact
|
||||
// Tests literals in attributes.
|
||||
|
||||
// Issue #623 - non-string meta items are not serialized correctly;
|
||||
// for now just forbid them
|
||||
#![feature(custom_attribute, attr_literals)]
|
||||
|
||||
#[foo = 1] //~ ERROR: non-string literals are not allowed in meta-items
|
||||
fn main() { }
|
||||
fn main() {
|
||||
#![hello("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))]
|
||||
#[align = 8]
|
||||
fn f() { }
|
||||
|
||||
#[vec(1, 2, 3)]
|
||||
fn g() { }
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ use syntax::ast;
|
|||
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use syntax_ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
|
||||
use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
|
||||
use syntax_pos::Span;
|
||||
|
|
@ -50,6 +49,7 @@ fn expand(cx: &mut ExtCtxt,
|
|||
generics: LifetimeBounds::empty(),
|
||||
associated_types: vec![],
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![
|
||||
MethodDef {
|
||||
name: "total_sum",
|
||||
|
|
|
|||
|
|
@ -21,12 +21,11 @@ extern crate rustc;
|
|||
extern crate rustc_plugin;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
use syntax_ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
|
||||
use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure};
|
||||
use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching};
|
||||
use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
|
||||
use syntax_pos::Span;
|
||||
|
|
@ -52,6 +51,7 @@ fn expand(cx: &mut ExtCtxt,
|
|||
generics: LifetimeBounds::empty(),
|
||||
associated_types: vec![],
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![
|
||||
MethodDef {
|
||||
name: "total_sum",
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ extern crate rustc;
|
|||
extern crate rustc_plugin;
|
||||
extern crate syntax_pos;
|
||||
|
||||
use syntax::ast::{self, Item, MetaItem, ImplItem, TraitItem, ItemKind};
|
||||
use syntax::ast::{self, Item, MetaItem, ItemKind};
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use syntax::ext::base::*;
|
||||
use syntax::ext::quote::rt::ToTokens;
|
||||
use syntax::parse::{self, token};
|
||||
use syntax::ptr::P;
|
||||
use syntax::tokenstream::TokenTree;
|
||||
|
|
@ -41,10 +43,13 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
token::intern("duplicate"),
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
MultiDecorator(Box::new(expand_duplicate)));
|
||||
reg.register_syntax_extension(
|
||||
token::intern("caller"),
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
MultiDecorator(Box::new(expand_caller)));
|
||||
}
|
||||
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||
-> Box<MacResult+'static> {
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
|
||||
if !tts.is_empty() {
|
||||
cx.span_fatal(sp, "make_a_1 takes no arguments");
|
||||
}
|
||||
|
|
@ -52,19 +57,18 @@ fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
|||
}
|
||||
|
||||
// See Issue #15750
|
||||
fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree])
|
||||
-> Box<MacResult+'static> {
|
||||
fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
|
||||
// Parse an expression and emit it unchanged.
|
||||
let mut parser = parse::new_parser_from_tts(cx.parse_sess(),
|
||||
cx.cfg(), tts.to_vec());
|
||||
let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec());
|
||||
let expr = parser.parse_expr().unwrap();
|
||||
MacEager::expr(quote_expr!(&mut *cx, $expr))
|
||||
}
|
||||
|
||||
fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
attr: &MetaItem,
|
||||
it: Annotatable) -> Vec<Annotatable> {
|
||||
_sp: Span,
|
||||
_attr: &MetaItem,
|
||||
it: Annotatable)
|
||||
-> Vec<Annotatable> {
|
||||
match it {
|
||||
Annotatable::Item(it) => vec![
|
||||
Annotatable::Item(P(Item {
|
||||
|
|
@ -74,7 +78,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
Annotatable::Item(quote_item!(cx, enum Foo3 { Bar }).unwrap()),
|
||||
Annotatable::Item(quote_item!(cx, #[cfg(any())] fn foo2() {}).unwrap()),
|
||||
],
|
||||
Annotatable::ImplItem(it) => vec![
|
||||
Annotatable::ImplItem(_it) => vec![
|
||||
quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| {
|
||||
match i.node {
|
||||
ItemKind::Impl(_, _, _, _, _, mut items) => {
|
||||
|
|
@ -84,7 +88,7 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
}
|
||||
})
|
||||
],
|
||||
Annotatable::TraitItem(it) => vec![
|
||||
Annotatable::TraitItem(_it) => vec![
|
||||
quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| {
|
||||
match i.node {
|
||||
ItemKind::Trait(_, _, _, mut items) => {
|
||||
|
|
@ -99,15 +103,14 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
|||
|
||||
// Create a duplicate of the annotatable, based on the MetaItem
|
||||
fn expand_duplicate(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
_sp: Span,
|
||||
mi: &MetaItem,
|
||||
it: &Annotatable,
|
||||
push: &mut FnMut(Annotatable))
|
||||
{
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
let copy_name = match mi.node {
|
||||
ast::MetaItemKind::List(_, ref xs) => {
|
||||
if let ast::MetaItemKind::Word(ref w) = xs[0].node {
|
||||
token::str_to_ident(&w)
|
||||
if let Some(word) = xs[0].word() {
|
||||
token::str_to_ident(&word.name())
|
||||
} else {
|
||||
cx.span_err(mi.span, "Expected word");
|
||||
return;
|
||||
|
|
@ -142,4 +145,69 @@ fn expand_duplicate(cx: &mut ExtCtxt,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn token_separate<T: ToTokens>(ecx: &ExtCtxt, things: &[T],
|
||||
token: token::Token) -> Vec<TokenTree> {
|
||||
let mut output: Vec<TokenTree> = vec![];
|
||||
for (i, thing) in things.iter().enumerate() {
|
||||
output.extend(thing.to_tokens(ecx));
|
||||
if i < things.len() - 1 {
|
||||
output.push(TokenTree::Token(DUMMY_SP, token.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
fn expand_caller(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
mi: &MetaItem,
|
||||
it: &Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
let (orig_fn_name, ret_type) = match *it {
|
||||
Annotatable::Item(ref item) => match item.node {
|
||||
ItemKind::Fn(ref decl, _, _, _, _, _) => {
|
||||
(item.ident, &decl.output)
|
||||
}
|
||||
_ => cx.span_fatal(item.span, "Only functions with return types can be annotated.")
|
||||
},
|
||||
_ => cx.span_fatal(sp, "Only functions can be annotated.")
|
||||
};
|
||||
|
||||
let (caller_name, arguments) = if let Some(list) = mi.meta_item_list() {
|
||||
if list.len() < 2 {
|
||||
cx.span_fatal(mi.span(), "Need a function name and at least one parameter.");
|
||||
}
|
||||
|
||||
let fn_name = match list[0].name() {
|
||||
Some(name) => token::str_to_ident(&name),
|
||||
None => cx.span_fatal(list[0].span(), "First parameter must be an ident.")
|
||||
};
|
||||
|
||||
(fn_name, &list[1..])
|
||||
} else {
|
||||
cx.span_fatal(mi.span, "Expected list.");
|
||||
};
|
||||
|
||||
let literals: Vec<ast::Lit> = arguments.iter().map(|arg| {
|
||||
if let Some(lit) = arg.literal() {
|
||||
lit.clone()
|
||||
} else {
|
||||
cx.span_fatal(arg.span(), "Expected literal.");
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let arguments = token_separate(cx, literals.as_slice(), token::Comma);
|
||||
if let ast::FunctionRetTy::Ty(ref rt) = *ret_type {
|
||||
push(Annotatable::Item(quote_item!(cx,
|
||||
fn $caller_name() -> $rt {
|
||||
$orig_fn_name($arguments)
|
||||
}).unwrap()))
|
||||
} else {
|
||||
push(Annotatable::Item(quote_item!(cx,
|
||||
fn $caller_name() {
|
||||
$orig_fn_name($arguments)
|
||||
}).unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foo() {}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use syntax::tokenstream;
|
|||
use rustc_plugin::Registry;
|
||||
|
||||
struct Expander {
|
||||
args: Vec<P<ast::MetaItem>>,
|
||||
args: Vec<ast::NestedMetaItem>,
|
||||
}
|
||||
|
||||
impl TTMacroExpander for Expander {
|
||||
|
|
@ -38,7 +38,7 @@ impl TTMacroExpander for Expander {
|
|||
ecx: &'cx mut ExtCtxt,
|
||||
sp: Span,
|
||||
_: &[tokenstream::TokenTree]) -> Box<MacResult+'cx> {
|
||||
let args = self.args.iter().map(|i| pprust::meta_item_to_string(&*i))
|
||||
let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
|
||||
.collect::<Vec<_>>().join(", ");
|
||||
let interned = token::intern_and_get_ident(&args[..]);
|
||||
MacEager::expr(ecx.expr_str(sp, interned))
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue