diff options
| author | bors <bors@rust-lang.org> | 2015-01-01 15:51:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-01-01 15:51:08 +0000 |
| commit | 39d74026663597a8d4ad0ab04e6d117bf9fd6ad4 (patch) | |
| tree | 0d444a5841d9d9b6d01c2c47c50e378ff6e9ea5f /src/libsyntax/feature_gate.rs | |
| parent | c594959cdff07b5545747809bb045bfa2868ebcc (diff) | |
| parent | 41da99dff417eadf8f296a93529d9810f79e1d1b (diff) | |
| download | rust-39d74026663597a8d4ad0ab04e6d117bf9fd6ad4.tar.gz rust-39d74026663597a8d4ad0ab04e6d117bf9fd6ad4.zip | |
auto merge of #20190 : cmr/rust/gate-macro-args, r=alexcrichton
Uses the same approach as https://github.com/rust-lang/rust/pull/17286 (and subsequent changes making it more correct), where the visitor will skip any pieces of the AST that are from "foreign code", where the spans don't line up, indicating that that piece of code is due to a macro expansion. If this breaks your code, read the error message to determine which feature gate you should add to your crate. Closes #18102 [breaking-change]
Diffstat (limited to 'src/libsyntax/feature_gate.rs')
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 123 |
1 files changed, 88 insertions, 35 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4607520655e..b2c2d7eb626 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -24,7 +24,7 @@ use ast::NodeId; use ast; use attr; use attr::AttrMetaMethods; -use codemap::Span; +use codemap::{CodeMap, Span}; use diagnostic::SpanHandler; use visit; use visit::Visitor; @@ -127,6 +127,7 @@ impl Features { struct Context<'a> { features: Vec<&'static str>, span_handler: &'a SpanHandler, + cm: &'a CodeMap, } impl<'a> Context<'a> { @@ -144,7 +145,71 @@ impl<'a> Context<'a> { } } -impl<'a, 'v> Visitor<'v> for Context<'a> { +struct MacroVisitor<'a> { + context: &'a Context<'a> +} + +impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { + fn visit_view_item(&mut self, i: &ast::ViewItem) { + match i.node { + ast::ViewItemExternCrate(..) => { + for attr in i.attrs.iter() { + if attr.name().get() == "phase"{ + self.context.gate_feature("phase", attr.span, + "compile time crate loading is \ + experimental and possibly buggy"); + } + } + }, + _ => { } + } + visit::walk_view_item(self, i) + } + + fn visit_mac(&mut self, macro: &ast::Mac) { + let ast::MacInvocTT(ref path, _, _) = macro.node; + let id = path.segments.last().unwrap().identifier; + + if id == token::str_to_ident("macro_rules") { + self.context.gate_feature("macro_rules", path.span, "macro definitions are \ + not stable enough for use and are subject to change"); + } + + else if id == token::str_to_ident("asm") { + self.context.gate_feature("asm", path.span, "inline assembly is not \ + stable enough for use and is subject to change"); + } + + else if id == token::str_to_ident("log_syntax") { + self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \ + stable enough for use and is subject to change"); + } + + else if id == token::str_to_ident("trace_macros") { + self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \ + stable enough for use and is subject to change"); + } + + else if id == token::str_to_ident("concat_idents") { + self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \ + stable enough for use and is subject to change"); + } + } +} + +struct PostExpansionVisitor<'a> { + context: &'a Context<'a> +} + +impl<'a> PostExpansionVisitor<'a> { + fn gate_feature(&self, feature: &str, span: Span, explain: &str) { + if !self.context.cm.span_is_internal(span) { + self.context.gate_feature(feature, span, explain) + } + } +} + +impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_name(&mut self, sp: Span, name: ast::Name) { if !token::get_name(name).get().is_ascii() { self.gate_feature("non_ascii_idents", sp, @@ -217,7 +282,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } ast::ItemImpl(_, _, _, _, ref items) => { - if attr::contains_name(i.attrs.as_slice(), + if attr::contains_name(i.attrs[], "unsafe_destructor") { self.gate_feature("unsafe_destructor", i.span, @@ -256,36 +321,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } } - fn visit_mac(&mut self, macro: &ast::Mac) { - let ast::MacInvocTT(ref path, _, _) = macro.node; - let id = path.segments.last().unwrap().identifier; - - if id == token::str_to_ident("macro_rules") { - self.gate_feature("macro_rules", path.span, "macro definitions are \ - not stable enough for use and are subject to change"); - } - - else if id == token::str_to_ident("asm") { - self.gate_feature("asm", path.span, "inline assembly is not \ - stable enough for use and is subject to change"); - } - - else if id == token::str_to_ident("log_syntax") { - self.gate_feature("log_syntax", path.span, "`log_syntax!` is not \ - stable enough for use and is subject to change"); - } - - else if id == token::str_to_ident("trace_macros") { - self.gate_feature("trace_macros", path.span, "`trace_macros` is not \ - stable enough for use and is subject to change"); - } - - else if id == token::str_to_ident("concat_idents") { - self.gate_feature("concat_idents", path.span, "`concat_idents` is not \ - stable enough for use and is subject to change"); - } - } - fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { if attr::contains_name(i.attrs[], "linkage") { self.gate_feature("linkage", i.span, @@ -371,10 +406,15 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } } -pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, Vec<Span>) { +fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate, + check: F) + -> (Features, Vec<Span>) + where F: FnOnce(&mut Context, &ast::Crate) +{ let mut cx = Context { features: Vec::new(), span_handler: span_handler, + cm: cm, }; let mut unknown_features = Vec::new(); @@ -419,7 +459,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, } } - visit::walk_crate(&mut cx, krate); + check(&mut cx, krate); (Features { default_type_params: cx.has_feature("default_type_params"), @@ -432,3 +472,16 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, }, unknown_features) } + +pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate) +-> (Features, Vec<Span>) { + check_crate_inner(cm, span_handler, krate, + |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate)) +} + +pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate) +-> (Features, Vec<Span>) { + check_crate_inner(cm, span_handler, krate, + |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx }, + krate)) +} |
