Skip to content

Commit

Permalink
Rewrite the unit tests in ext/expand.rs as a compile-fail test.
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried committed Sep 13, 2016
1 parent a9821e1 commit 20b43b2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 107 deletions.
107 changes: 0 additions & 107 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,110 +803,3 @@ impl Folder for Marker {
fn mark_tts(tts: &[TokenTree], m: Mark) -> Vec<TokenTree> {
noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None})
}


#[cfg(test)]
mod tests {
use super::{expand_crate, ExpansionConfig};
use ast;
use ext::base::{ExtCtxt, DummyResolver};
use parse;
use util::parser_testing::{string_to_parser};
use visit;
use visit::Visitor;

// a visitor that extracts the paths
// from a given thingy and puts them in a mutable
// array (passed in to the traversal)
#[derive(Clone)]
struct PathExprFinderContext {
path_accumulator: Vec<ast::Path> ,
}

impl Visitor for PathExprFinderContext {
fn visit_expr(&mut self, expr: &ast::Expr) {
if let ast::ExprKind::Path(None, ref p) = expr.node {
self.path_accumulator.push(p.clone());
}
visit::walk_expr(self, expr);
}
}

// these following tests are quite fragile, in that they don't test what
// *kind* of failure occurs.

fn test_ecfg() -> ExpansionConfig<'static> {
ExpansionConfig::default("test".to_string())
}

// make sure that macros can't escape fns
#[should_panic]
#[test] fn macros_cant_escape_fns_test () {
let src = "fn bogus() {macro_rules! z (() => (3+4));}\
fn inty() -> i32 { z!() }".to_string();
let sess = parse::ParseSess::new();
let crate_ast = parse::parse_crate_from_source_str(
"<test>".to_string(),
src,
Vec::new(), &sess).unwrap();
// should fail:
let mut loader = DummyResolver;
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
expand_crate(&mut ecx, vec![], crate_ast);
}

// make sure that macros can't escape modules
#[should_panic]
#[test] fn macros_cant_escape_mods_test () {
let src = "mod foo {macro_rules! z (() => (3+4));}\
fn inty() -> i32 { z!() }".to_string();
let sess = parse::ParseSess::new();
let crate_ast = parse::parse_crate_from_source_str(
"<test>".to_string(),
src,
Vec::new(), &sess).unwrap();
let mut loader = DummyResolver;
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
expand_crate(&mut ecx, vec![], crate_ast);
}

// macro_use modules should allow macros to escape
#[test] fn macros_can_escape_flattened_mods_test () {
let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\
fn inty() -> i32 { z!() }".to_string();
let sess = parse::ParseSess::new();
let crate_ast = parse::parse_crate_from_source_str(
"<test>".to_string(),
src,
Vec::new(), &sess).unwrap();
let mut loader = DummyResolver;
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
expand_crate(&mut ecx, 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...
let mut loader = DummyResolver;
let mut ecx = ExtCtxt::new(&ps, vec![], test_ecfg(), &mut loader);
expand_crate(&mut ecx, vec![], crate_ast)
}

#[test] fn macro_tokens_should_match(){
expand_crate_str(
"macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string());
}

// should be able to use a bound identifier as a literal in a macro definition:
#[test] fn self_macro_parsing(){
expand_crate_str(
"macro_rules! foo ((zz) => (287;));
fn f(zz: i32) {foo!(zz);}".to_string()
);
}

// create a really evil test case where a $x appears inside a binding of $x
// but *shouldn't* bind because it was inserted by a different macro....
// can't write this test case until we have macro-generating macros.
}
46 changes: 46 additions & 0 deletions src/test/compile-fail/macro-expansion-tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.

mod macros_cant_escape_fns {
fn f() {
macro_rules! m { () => { 3 + 4 } }
}
fn g() -> i32 { m!() } //~ ERROR macro undefined
}

mod macros_cant_escape_mods {
mod f {
macro_rules! m { () => { 3 + 4 } }
}
fn g() -> i32 { m!() } //~ ERROR macro undefined
}

mod macros_can_escape_flattened_mods_test {
#[macro_use]
mod f {
macro_rules! m { () => { 3 + 4 } }
}
fn g() -> i32 { m!() }
}

fn macro_tokens_should_match() {
macro_rules! m { (a) => { 13 } }
m!(a);
}

// should be able to use a bound identifier as a literal in a macro definition:
fn self_macro_parsing() {
macro_rules! foo { (zz) => { 287; } }
fn f(zz: i32) {
foo!(zz);
}
}

fn main() {}

0 comments on commit 20b43b2

Please sign in to comment.