From 173b3fd155fe5c2acfc8a8f454b839706ff7a552 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Tue, 18 Aug 2015 12:26:27 -0700 Subject: [PATCH] Sync with Rust (dc9b74f) --- syntex_syntax/src/abi.rs | 2 + syntex_syntax/src/ast.rs | 38 ++++--- syntex_syntax/src/ast_util.rs | 33 +++---- syntex_syntax/src/attr.rs | 51 ++++++---- syntex_syntax/src/config.rs | 28 ++++-- syntex_syntax/src/diagnostics/macros.rs | 12 +++ syntex_syntax/src/ext/base.rs | 6 +- syntex_syntax/src/ext/cfg.rs | 3 +- syntex_syntax/src/ext/deriving/generic/mod.rs | 2 +- syntex_syntax/src/ext/expand.rs | 25 ++--- syntex_syntax/src/ext/tt/transcribe.rs | 2 +- syntex_syntax/src/feature_gate.rs | 98 ++++++++++++++++++- syntex_syntax/src/lib.rs | 4 +- syntex_syntax/src/test.rs | 4 +- syntex_syntax/src/visit.rs | 11 --- 15 files changed, 220 insertions(+), 99 deletions(-) diff --git a/syntex_syntax/src/abi.rs b/syntex_syntax/src/abi.rs index 50c86a80..c0fe541e 100644 --- a/syntex_syntax/src/abi.rs +++ b/syntex_syntax/src/abi.rs @@ -47,6 +47,7 @@ pub enum Abi { System, RustIntrinsic, RustCall, + PlatformIntrinsic, } #[allow(non_camel_case_types)] @@ -95,6 +96,7 @@ const AbiDatas: &'static [AbiData] = &[ AbiData {abi: System, name: "system" }, AbiData {abi: RustIntrinsic, name: "rust-intrinsic" }, AbiData {abi: RustCall, name: "rust-call" }, + AbiData {abi: PlatformIntrinsic, name: "platform-intrinsic" } ]; /// Returns the ABI with the given name (if any). diff --git a/syntex_syntax/src/ast.rs b/syntex_syntax/src/ast.rs index bcc90dc4..2d72c8fe 100644 --- a/syntex_syntax/src/ast.rs +++ b/syntex_syntax/src/ast.rs @@ -23,7 +23,6 @@ pub use self::FloatTy::*; pub use self::FunctionRetTy::*; pub use self::ForeignItem_::*; pub use self::ImplItem_::*; -pub use self::InlinedItem::*; pub use self::IntTy::*; pub use self::Item_::*; pub use self::KleeneOp::*; @@ -475,7 +474,7 @@ pub enum WherePredicate { /// A lifetime predicate, e.g. `'a: 'b+'c` RegionPredicate(WhereRegionPredicate), /// An equality predicate (unsupported) - EqPredicate(WhereEqPredicate) + EqPredicate(WhereEqPredicate), } /// A type bound, eg `for<'c> Foo: Send+Clone+'c` @@ -1340,6 +1339,15 @@ impl IntTy { TyI16 | TyI32 | TyI64 => 3, } } + pub fn bit_width(&self) -> Option { + Some(match *self { + TyIs => return None, + TyI8 => 8, + TyI16 => 16, + TyI32 => 32, + TyI64 => 64, + }) + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] @@ -1358,6 +1366,15 @@ impl UintTy { TyU16 | TyU32 | TyU64 => 3, } } + pub fn bit_width(&self) -> Option { + Some(match *self { + TyUs => return None, + TyU8 => 8, + TyU16 => 16, + TyU32 => 32, + TyU64 => 64, + }) + } } impl fmt::Debug for UintTy { @@ -1396,6 +1413,12 @@ impl FloatTy { TyF32 | TyF64 => 3, // add F128 handling here } } + pub fn bit_width(&self) -> usize { + match *self { + TyF32 => 32, + TyF64 => 64, + } + } } // Bind a type to an associated type: `A=Foo`. @@ -1925,17 +1948,6 @@ impl ForeignItem_ { } } -/// The data we save and restore about an inlined item or method. This is not -/// part of the AST that we parse from a file, but it becomes part of the tree -/// that we trans. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum InlinedItem { - IIItem(P), - IITraitItem(DefId /* impl id */, P), - IIImplItem(DefId /* impl id */, P), - IIForeign(P), -} - /// A macro definition, in this crate or imported from another. /// /// Not parsed directly, but created on macro import or `macro_rules!` expansion. diff --git a/syntex_syntax/src/ast_util.rs b/syntex_syntax/src/ast_util.rs index 83d3c9c4..7aff92ec 100644 --- a/syntex_syntax/src/ast_util.rs +++ b/syntex_syntax/src/ast_util.rs @@ -503,19 +503,18 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { } } -pub fn visit_ids_for_inlined_item(item: &InlinedItem, - operation: &mut O) { - let mut id_visitor = IdVisitor { - operation: operation, - pass_through_items: true, - visited_outermost: false, - }; - - visit::walk_inlined_item(&mut id_visitor, item); +pub struct IdRangeComputingVisitor { + result: IdRange, } -struct IdRangeComputingVisitor { - result: IdRange, +impl IdRangeComputingVisitor { + pub fn new() -> IdRangeComputingVisitor { + IdRangeComputingVisitor { result: IdRange::max() } + } + + pub fn result(&self) -> IdRange { + self.result + } } impl IdVisitingOperation for IdRangeComputingVisitor { @@ -524,14 +523,6 @@ impl IdVisitingOperation for IdRangeComputingVisitor { } } -pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange { - let mut visitor = IdRangeComputingVisitor { - result: IdRange::max() - }; - visit_ids_for_inlined_item(item, &mut visitor); - visitor.result -} - /// Computes the id range for a single fn body, ignoring nested items. pub fn compute_id_range_for_fn_body(fk: visit::FnKind, decl: &FnDecl, @@ -540,9 +531,7 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind, id: NodeId) -> IdRange { - let mut visitor = IdRangeComputingVisitor { - result: IdRange::max() - }; + let mut visitor = IdRangeComputingVisitor::new(); let mut id_visitor = IdVisitor { operation: &mut visitor, pass_through_items: false, diff --git a/syntex_syntax/src/attr.rs b/syntex_syntax/src/attr.rs index ed3ee768..7540c2ff 100644 --- a/syntex_syntax/src/attr.rs +++ b/syntex_syntax/src/attr.rs @@ -10,9 +10,6 @@ // Functions dealing with attributes and meta items -// BitSet -#![allow(deprecated)] - pub use self::StabilityLevel::*; pub use self::ReprAttr::*; pub use self::IntType::*; @@ -22,26 +19,40 @@ use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, Meta use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use diagnostic::SpanHandler; +use feature_gate::GatedCfg; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::token::{InternedString, intern_and_get_ident}; use parse::token; use ptr::P; use std::cell::{RefCell, Cell}; -use std::collections::BitSet; use std::collections::HashSet; use std::fmt; -thread_local! { static USED_ATTRS: RefCell = RefCell::new(BitSet::new()) } +thread_local! { + static USED_ATTRS: RefCell> = RefCell::new(Vec::new()) +} pub fn mark_used(attr: &Attribute) { let AttrId(id) = attr.node.id; - USED_ATTRS.with(|slot| slot.borrow_mut().insert(id)); + USED_ATTRS.with(|slot| { + let idx = (id / 64) as usize; + let shift = id % 64; + if slot.borrow().len() <= idx { + slot.borrow_mut().resize(idx + 1, 0); + } + slot.borrow_mut()[idx] |= 1 << shift; + }); } pub fn is_used(attr: &Attribute) -> bool { let AttrId(id) = attr.node.id; - USED_ATTRS.with(|slot| slot.borrow().contains(&id)) + USED_ATTRS.with(|slot| { + let idx = (id / 64) as usize; + let shift = id % 64; + slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0) + .unwrap_or(false) + }) } pub trait AttrMetaMethods { @@ -347,24 +358,28 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { } /// Tests if a cfg-pattern matches the cfg set -pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P], cfg: &ast::MetaItem) -> bool { +pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P], cfg: &ast::MetaItem, + feature_gated_cfgs: &mut Vec) -> bool { match cfg.node { ast::MetaList(ref pred, ref mis) if &pred[..] == "any" => - mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)), ast::MetaList(ref pred, ref mis) if &pred[..] == "all" => - mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)), ast::MetaList(ref pred, ref mis) if &pred[..] == "not" => { if mis.len() != 1 { diagnostic.span_err(cfg.span, "expected 1 cfg-pattern"); return false; } - !cfg_matches(diagnostic, cfgs, &*mis[0]) + !cfg_matches(diagnostic, cfgs, &*mis[0], feature_gated_cfgs) } ast::MetaList(ref pred, _) => { diagnostic.span_err(cfg.span, &format!("invalid predicate `{}`", pred)); false }, - ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg), + ast::MetaWord(_) | ast::MetaNameValue(..) => { + feature_gated_cfgs.extend(GatedCfg::gate(cfg)); + contains(cfgs, cfg) + } } } @@ -522,10 +537,9 @@ fn find_stability_generic<'a, } } else if stab.as_ref().map_or(false, |s| s.level == Unstable && s.issue.is_none()) { // non-deprecated unstable items need to point to issues. - // FIXME: uncomment this error - // diagnostic.span_err(item_sp, - // "non-deprecated unstable items need to point \ - // to an issue with `issue = \"NNN\"`"); + diagnostic.span_err(item_sp, + "non-deprecated unstable items need to point \ + to an issue with `issue = \"NNN\"`"); } (stab, used_attrs) @@ -570,6 +584,7 @@ pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec Some(ReprExtern), "packed" => Some(ReprPacked), + "simd" => Some(ReprSimd), _ => match int_type_of_word(&word) { Some(ity) => Some(ReprInt(item.span, ity)), None => { @@ -619,6 +634,7 @@ pub enum ReprAttr { ReprInt(Span, IntType), ReprExtern, ReprPacked, + ReprSimd, } impl ReprAttr { @@ -627,7 +643,8 @@ impl ReprAttr { ReprAny => false, ReprInt(_sp, ity) => ity.is_ffi_safe(), ReprExtern => true, - ReprPacked => false + ReprPacked => false, + ReprSimd => true, } } } diff --git a/syntex_syntax/src/config.rs b/syntex_syntax/src/config.rs index 366806bc..faf0b51c 100644 --- a/syntex_syntax/src/config.rs +++ b/syntex_syntax/src/config.rs @@ -10,6 +10,7 @@ use attr::AttrMetaMethods; use diagnostic::SpanHandler; +use feature_gate::GatedCfg; use fold::Folder; use {ast, fold, attr}; use codemap::{Spanned, respan}; @@ -25,10 +26,13 @@ struct Context where F: FnMut(&[ast::Attribute]) -> bool { // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration -pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { - let krate = process_cfg_attr(diagnostic, krate); +pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate, + feature_gated_cfgs: &mut Vec) + -> ast::Crate +{ + let krate = process_cfg_attr(diagnostic, krate, feature_gated_cfgs); let config = krate.config.clone(); - strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs)) + strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs, feature_gated_cfgs)) } impl fold::Folder for Context where F: FnMut(&[ast::Attribute]) -> bool { @@ -248,7 +252,8 @@ fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool // Determine if an item should be translated in the current crate // configuration based on the item's attributes -fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attribute]) -> bool { +fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attribute], + feature_gated_cfgs: &mut Vec) -> bool { attrs.iter().all(|attr| { let mis = match attr.node.value.node { ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis, @@ -260,25 +265,29 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attr return true; } - attr::cfg_matches(diagnostic, cfg, &*mis[0]) + attr::cfg_matches(diagnostic, cfg, &*mis[0], + feature_gated_cfgs) }) } -struct CfgAttrFolder<'a> { +struct CfgAttrFolder<'a, 'b> { diag: &'a SpanHandler, config: ast::CrateConfig, + feature_gated_cfgs: &'b mut Vec } // Process `#[cfg_attr]`. -fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { +fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate, + feature_gated_cfgs: &mut Vec) -> ast::Crate { let mut fld = CfgAttrFolder { diag: diagnostic, config: krate.config.clone(), + feature_gated_cfgs: feature_gated_cfgs, }; fld.fold_crate(krate) } -impl<'a> fold::Folder for CfgAttrFolder<'a> { +impl<'a,'b> fold::Folder for CfgAttrFolder<'a,'b> { fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { if !attr.check_name("cfg_attr") { return fold::noop_fold_attribute(attr, self); @@ -299,7 +308,8 @@ impl<'a> fold::Folder for CfgAttrFolder<'a> { } }; - if attr::cfg_matches(self.diag, &self.config[..], &cfg) { + if attr::cfg_matches(self.diag, &self.config[..], &cfg, + self.feature_gated_cfgs) { Some(respan(mi.span, ast::Attribute_ { id: attr::mk_attr_id(), style: attr.node.style, diff --git a/syntex_syntax/src/diagnostics/macros.rs b/syntex_syntax/src/diagnostics/macros.rs index 669b930e..3c8347f8 100644 --- a/syntex_syntax/src/diagnostics/macros.rs +++ b/syntex_syntax/src/diagnostics/macros.rs @@ -30,6 +30,18 @@ macro_rules! span_err { }) } +#[macro_export] +macro_rules! span_err_or_warn { + ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ + __diagnostic_used!($code); + if $is_warning { + $session.span_warn_with_code($span, &format!($($message)*), stringify!($code)) + } else { + $session.span_err_with_code($span, &format!($($message)*), stringify!($code)) + } + }) +} + #[macro_export] macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ diff --git a/syntex_syntax/src/ext/base.rs b/syntex_syntax/src/ext/base.rs index d4b5e67e..ef11a2bd 100644 --- a/syntex_syntax/src/ext/base.rs +++ b/syntex_syntax/src/ext/base.rs @@ -17,6 +17,7 @@ use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion}; use ext; use ext::expand; use ext::tt::macro_rules; +use feature_gate::GatedCfg; use parse; use parse::parser; use parse::token; @@ -632,6 +633,7 @@ pub struct ExtCtxt<'a> { pub backtrace: ExpnId, pub ecfg: expand::ExpansionConfig<'a>, pub crate_root: Option<&'static str>, + pub feature_gated_cfgs: &'a mut Vec, pub mod_path: Vec , pub exported_macros: Vec, @@ -642,7 +644,8 @@ pub struct ExtCtxt<'a> { impl<'a> ExtCtxt<'a> { pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, - ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> { + ecfg: expand::ExpansionConfig<'a>, + feature_gated_cfgs: &'a mut Vec) -> ExtCtxt<'a> { let env = initial_syntax_expander_table(&ecfg); ExtCtxt { parse_sess: parse_sess, @@ -651,6 +654,7 @@ impl<'a> ExtCtxt<'a> { mod_path: Vec::new(), ecfg: ecfg, crate_root: None, + feature_gated_cfgs: feature_gated_cfgs, exported_macros: Vec::new(), syntax_env: env, recursion_count: 0, diff --git a/syntex_syntax/src/ext/cfg.rs b/syntex_syntax/src/ext/cfg.rs index 8af7fb7b..aa654e30 100644 --- a/syntex_syntax/src/ext/cfg.rs +++ b/syntex_syntax/src/ext/cfg.rs @@ -34,6 +34,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, return DummyResult::expr(sp); } - let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg); + let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg, + cx.feature_gated_cfgs); MacEager::expr(cx.expr_bool(sp, matches_cfg)) } diff --git a/syntex_syntax/src/ext/deriving/generic/mod.rs b/syntex_syntax/src/ext/deriving/generic/mod.rs index 1f4860b7..f8f63e94 100644 --- a/syntex_syntax/src/ext/deriving/generic/mod.rs +++ b/syntex_syntax/src/ext/deriving/generic/mod.rs @@ -739,7 +739,7 @@ fn find_repr_type_name(diagnostic: &SpanHandler, for a in type_attrs { for r in &attr::find_repr_attrs(diagnostic, a) { repr_type_name = match *r { - attr::ReprAny | attr::ReprPacked => continue, + attr::ReprAny | attr::ReprPacked | attr::ReprSimd => continue, attr::ReprExtern => "i32", attr::ReprInt(_, attr::SignedInt(ast::TyIs)) => "isize", diff --git a/syntex_syntax/src/ext/expand.rs b/syntex_syntax/src/ext/expand.rs index 6c09d6c1..4f89b349 100644 --- a/syntex_syntax/src/ext/expand.rs +++ b/syntex_syntax/src/ext/expand.rs @@ -21,7 +21,7 @@ use attr::AttrMetaMethods; use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, CompilerExpansion}; use ext::base::*; -use feature_gate::{self, Features}; +use feature_gate::{self, Features, GatedCfg}; use fold; use fold::*; use parse; @@ -385,16 +385,7 @@ pub fn expand_expr(e: P, fld: &mut MacroExpander) -> P { // expand let head = fld.fold_expr(head); - // create an hygienic ident - let iter = { - let ident = fld.cx.ident_of("iter"); - let new_ident = fresh_name(&ident); - let rename = (ident, new_ident); - let mut rename_list = vec![rename]; - let mut rename_fld = IdentRenamer{ renames: &mut rename_list }; - - rename_fld.fold_ident(ident) - }; + let iter = token::gensym_ident("iter"); let pat_span = fld.new_span(pat.span); // `::std::option::Option::Some() => ` @@ -1696,8 +1687,10 @@ pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess, // these are the macros being imported to this crate: imported_macros: Vec, user_exts: Vec, + feature_gated_cfgs: &mut Vec, c: Crate) -> Crate { - let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); + let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg, + feature_gated_cfgs); if std_inject::no_core(&c) { cx.crate_root = None; } else if std_inject::no_std(&c) { @@ -1887,7 +1880,7 @@ mod tests { src, Vec::new(), &sess); // should fail: - expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast); } // make sure that macros can't escape modules @@ -1900,7 +1893,7 @@ mod tests { "".to_string(), src, Vec::new(), &sess); - expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast); } // macro_use modules should allow macros to escape @@ -1912,14 +1905,14 @@ mod tests { "".to_string(), src, Vec::new(), &sess); - expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast); + expand_crate(&sess, test_ecfg(), vec!(), vec!(), &mut vec![], crate_ast); } fn expand_crate_str(crate_str: String) -> ast::Crate { let ps = parse::ParseSess::new(); let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod()); // the cfg argument actually does matter, here... - expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast) + expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast) } // find the pat_ident paths in a crate diff --git a/syntex_syntax/src/ext/tt/transcribe.rs b/syntex_syntax/src/ext/tt/transcribe.rs index 0ca755c9..b07bd099 100644 --- a/syntex_syntax/src/ext/tt/transcribe.rs +++ b/syntex_syntax/src/ext/tt/transcribe.rs @@ -305,7 +305,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } MatchedSeq(..) => { panic!(r.sp_diag.span_fatal( - r.cur_span, /* blame the macro writer */ + sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident))); } diff --git a/syntex_syntax/src/feature_gate.rs b/syntex_syntax/src/feature_gate.rs index 87149ff8..f5a0a2f4 100644 --- a/syntex_syntax/src/feature_gate.rs +++ b/syntex_syntax/src/feature_gate.rs @@ -37,6 +37,7 @@ use visit::Visitor; use parse::token::{self, InternedString}; use std::ascii::AsciiExt; +use std::cmp; // If you change this list without updating src/doc/reference.md, @cmr will be sad // Don't ever remove anything from this list; set them to 'Removed'. @@ -85,6 +86,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("on_unimplemented", "1.0.0", Active), ("simd_ffi", "1.0.0", Active), ("allocator", "1.0.0", Active), + ("needs_allocator", "1.4.0", Active), ("linked_from", "1.3.0", Active), ("if_let", "1.0.0", Accepted), @@ -176,6 +178,15 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // Allows macros to appear in the type position. ("type_macros", "1.3.0", Active), + + // allow `repr(simd)`, and importing the various simd intrinsics + ("repr_simd", "1.4.0", Active), + + // Allows cfg(target_feature = "..."). + ("cfg_target_feature", "1.4.0", Active), + + // allow `extern "platform-intrinsic" { ... }` + ("platform_intrinsics", "1.4.0", Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -253,6 +264,9 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ is an experimental feature")), ("allocator", Gated("allocator", "the `#[allocator]` attribute is an experimental feature")), + ("needs_allocator", Gated("needs_allocator", "the `#[needs_allocator]` \ + attribute is an experimental \ + feature")), ("rustc_variance", Gated("rustc_attrs", "the `#[rustc_variance]` attribute \ is an experimental feature")), @@ -320,6 +334,59 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("recursion_limit", CrateLevel), ]; +macro_rules! cfg_fn { + (|$x: ident| $e: expr) => {{ + fn f($x: &Features) -> bool { + $e + } + f as fn(&Features) -> bool + }} +} +// cfg(...)'s that are feature gated +const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[ + // (name in cfg, feature, function to check if the feature is enabled) + ("target_feature", "cfg_target_feature", cfg_fn!(|x| x.cfg_target_feature)), +]; + +#[derive(Debug, Eq, PartialEq)] +pub struct GatedCfg { + span: Span, + index: usize, +} +impl Ord for GatedCfg { + fn cmp(&self, other: &GatedCfg) -> cmp::Ordering { + (self.span.lo.0, self.span.hi.0, self.index) + .cmp(&(other.span.lo.0, other.span.hi.0, other.index)) + } +} +impl PartialOrd for GatedCfg { + fn partial_cmp(&self, other: &GatedCfg) -> Option { + Some(self.cmp(other)) + } +} + +impl GatedCfg { + pub fn gate(cfg: &ast::MetaItem) -> Option { + let name = cfg.name(); + GATED_CFGS.iter() + .position(|info| info.0 == name) + .map(|idx| { + GatedCfg { + span: cfg.span, + index: idx + } + }) + } + pub fn check_and_emit(&self, diagnostic: &SpanHandler, features: &Features) { + let (cfg, feature, has_feature) = GATED_CFGS[self.index]; + if !has_feature(features) { + let explain = format!("`cfg({})` is experimental and subject to change", cfg); + emit_feature_err(diagnostic, feature, self.span, &explain); + } + } +} + + #[derive(PartialEq, Copy, Clone, Debug)] pub enum AttributeType { /// Normal, builtin attribute that is consumed @@ -365,6 +432,7 @@ pub struct Features { pub static_recursion: bool, pub default_type_parameter_fallback: bool, pub type_macros: bool, + pub cfg_target_feature: bool, } impl Features { @@ -392,6 +460,7 @@ impl Features { static_recursion: false, default_type_parameter_fallback: false, type_macros: false, + cfg_target_feature: false, } } } @@ -626,10 +695,16 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { across platforms, it is recommended to \ use `#[link(name = \"foo\")]` instead") } - if foreign_module.abi == Abi::RustIntrinsic { - self.gate_feature("intrinsics", - i.span, - "intrinsics are subject to change") + let maybe_feature = match foreign_module.abi { + Abi::RustIntrinsic => Some(("intrinsics", "intrinsics are subject to change")), + Abi::PlatformIntrinsic => { + Some(("platform_intrinsics", + "platform intrinsics are experimental and possibly buggy")) + } + _ => None + }; + if let Some((feature, msg)) = maybe_feature { + self.gate_feature(feature, i.span, msg) } } @@ -656,6 +731,20 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { if attr::contains_name(&i.attrs[..], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); + self.context.span_handler.span_warn(i.span, + "the `#[simd]` attribute is deprecated, \ + use `#[repr(simd)]` instead"); + } + for attr in &i.attrs { + if attr.name() == "repr" { + for item in attr.meta_item_list().unwrap_or(&[]) { + if item.name() == "simd" { + self.gate_feature("repr_simd", i.span, + "SIMD types are experimental and possibly buggy"); + + } + } + } } } @@ -896,6 +985,7 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, static_recursion: cx.has_feature("static_recursion"), default_type_parameter_fallback: cx.has_feature("default_type_parameter_fallback"), type_macros: cx.has_feature("type_macros"), + cfg_target_feature: cx.has_feature("cfg_target_feature"), } } diff --git a/syntex_syntax/src/lib.rs b/syntex_syntax/src/lib.rs index 94c92040..0d1fa6dd 100644 --- a/syntex_syntax/src/lib.rs +++ b/syntex_syntax/src/lib.rs @@ -17,7 +17,7 @@ // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) #![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "syntax"] -#![unstable(feature = "rustc_private")] +#![unstable(feature = "rustc_private", issue = "27812")] #![staged_api] #![crate_type = "dylib"] #![crate_type = "rlib"] @@ -26,7 +26,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(associated_consts)] -#![feature(bitset)] #![feature(drain)] #![feature(filling_drop)] #![feature(libc)] @@ -38,6 +37,7 @@ #![feature(str_escape)] #![feature(unicode)] #![feature(vec_push_all)] +#![feature(vec_resize)] extern crate fmt_macros; extern crate serialize; diff --git a/syntex_syntax/src/test.rs b/syntex_syntax/src/test.rs index ea99291d..26fb287c 100644 --- a/syntex_syntax/src/test.rs +++ b/syntex_syntax/src/test.rs @@ -246,11 +246,13 @@ fn generate_test_harness(sess: &ParseSess, krate: ast::Crate, cfg: &ast::CrateConfig, sd: &diagnostic::SpanHandler) -> ast::Crate { + let mut feature_gated_cfgs = vec![]; let mut cx: TestCtxt = TestCtxt { sess: sess, span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, cfg.clone(), - ExpansionConfig::default("test".to_string())), + ExpansionConfig::default("test".to_string()), + &mut feature_gated_cfgs), path: Vec::new(), testfns: Vec::new(), reexport_test_harness_main: reexport_test_harness_main, diff --git a/syntex_syntax/src/visit.rs b/syntex_syntax/src/visit.rs index ad144d60..25956433 100644 --- a/syntex_syntax/src/visit.rs +++ b/syntex_syntax/src/visit.rs @@ -142,17 +142,6 @@ pub trait Visitor<'v> : Sized { fn visit_attribute(&mut self, _attr: &'v Attribute) {} } -pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem) - where V: Visitor<'v> { - match *item { - IIItem(ref i) => visitor.visit_item(&**i), - IIForeign(ref i) => visitor.visit_foreign_item(&**i), - IITraitItem(_, ref ti) => visitor.visit_trait_item(ti), - IIImplItem(_, ref ii) => visitor.visit_impl_item(ii), - } -} - - pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID); for attr in &krate.attrs {