@@ -1265,7 +1265,7 @@ mod tests {
12651265 use ext:: mtwt;
12661266 use fold:: Folder ;
12671267 use parse;
1268- use parse:: token:: { self , keywords } ;
1268+ use parse:: token;
12691269 use util:: parser_testing:: { string_to_parser} ;
12701270 use util:: parser_testing:: { string_to_pat, string_to_crate, strs_to_idents} ;
12711271 use visit;
@@ -1395,267 +1395,10 @@ mod tests {
13951395 ) ;
13961396 }
13971397
1398- // renaming tests expand a crate and then check that the bindings match
1399- // the right varrefs. The specification of the test case includes the
1400- // text of the crate, and also an array of arrays. Each element in the
1401- // outer array corresponds to a binding in the traversal of the AST
1402- // induced by visit. Each of these arrays contains a list of indexes,
1403- // interpreted as the varrefs in the varref traversal that this binding
1404- // should match. So, for instance, in a program with two bindings and
1405- // three varrefs, the array [[1, 2], [0]] would indicate that the first
1406- // binding should match the second two varrefs, and the second binding
1407- // should match the first varref.
1408- //
1409- // Put differently; this is a sparse representation of a boolean matrix
1410- // indicating which bindings capture which identifiers.
1411- //
1412- // Note also that this matrix is dependent on the implicit ordering of
1413- // the bindings and the varrefs discovered by the name-finder and the path-finder.
1414- //
1415- // The comparisons are done post-mtwt-resolve, so we're comparing renamed
1416- // names; differences in marks don't matter any more.
1417- //
1418- // oog... I also want tests that check "bound-identifier-=?". That is,
1419- // not just "do these have the same name", but "do they have the same
1420- // name *and* the same marks"? Understanding this is really pretty painful.
1421- // in principle, you might want to control this boolean on a per-varref basis,
1422- // but that would make things even harder to understand, and might not be
1423- // necessary for thorough testing.
1424- type RenamingTest = ( & ' static str , Vec < Vec < usize > > , bool ) ;
1425-
1426- #[ test]
1427- fn automatic_renaming ( ) {
1428- let tests: Vec < RenamingTest > =
1429- vec ! ( // b & c should get new names throughout, in the expr too:
1430- ( "fn a() -> i32 { let b = 13; let c = b; b+c }" ,
1431- vec!( vec!( 0 , 1 ) , vec!( 2 ) ) , false ) ,
1432- // both x's should be renamed (how is this causing a bug?)
1433- ( "fn main () {let x: i32 = 13;x;}" ,
1434- vec!( vec!( 0 ) ) , false ) ,
1435- // the use of b after the + should be renamed, the other one not:
1436- ( "macro_rules! f (($x:ident) => (b + $x)); fn a() -> i32 { let b = 13; f!(b)}" ,
1437- vec!( vec!( 1 ) ) , false ) ,
1438- // the b before the plus should not be renamed (requires marks)
1439- ( "macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> i32 { f!(b)}" ,
1440- vec!( vec!( 1 ) ) , false ) ,
1441- // the marks going in and out of letty should cancel, allowing that $x to
1442- // capture the one following the semicolon.
1443- // this was an awesome test case, and caught a *lot* of bugs.
1444- ( "macro_rules! letty(($x:ident) => (let $x = 15;));
1445- macro_rules! user(($x:ident) => ({letty!($x); $x}));
1446- fn main() -> i32 {user!(z)}" ,
1447- vec!( vec!( 0 ) ) , false )
1448- ) ;
1449- for ( idx, s) in tests. iter ( ) . enumerate ( ) {
1450- run_renaming_test ( s, idx) ;
1451- }
1452- }
1453-
1454- // no longer a fixme #8062: this test exposes a *potential* bug; our system does
1455- // not behave exactly like MTWT, but a conversation with Matthew Flatt
1456- // suggests that this can only occur in the presence of local-expand, which
1457- // we have no plans to support. ... unless it's needed for item hygiene....
1458- #[ ignore]
1459- #[ test]
1460- fn issue_8062 ( ) {
1461- run_renaming_test (
1462- & ( "fn main() {let hrcoo = 19; macro_rules! getx(()=>(hrcoo)); getx!();}" ,
1463- vec ! ( vec!( 0 ) ) , true ) , 0 )
1464- }
1465-
1466- // FIXME #6994:
1467- // the z flows into and out of two macros (g & f) along one path, and one
1468- // (just g) along the other, so the result of the whole thing should
1469- // be "let z_123 = 3; z_123"
1470- #[ ignore]
1471- #[ test]
1472- fn issue_6994 ( ) {
1473- run_renaming_test (
1474- & ( "macro_rules! g (($x:ident) =>
1475- ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)}));
1476- fn a(){g!(z)}" ,
1477- vec ! ( vec!( 0 ) ) , false ) ,
1478- 0 )
1479- }
1480-
1481- // match variable hygiene. Should expand into
1482- // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}}
1483- #[ test]
1484- fn issue_9384 ( ) {
1485- run_renaming_test (
1486- & ( "macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}}));
1487- fn z() {match 8 {x => bad_macro!(x)}}" ,
1488- // NB: the third "binding" is the repeat of the second one.
1489- vec ! ( vec!( 1 , 3 ) , vec!( 0 , 2 ) , vec!( 0 , 2 ) ) ,
1490- true ) ,
1491- 0 )
1492- }
1493-
1494- // interpolated nodes weren't getting labeled.
1495- // should expand into
1496- // fn main(){let g1_1 = 13; g1_1}}
1497- #[ test]
1498- fn pat_expand_issue_15221 ( ) {
1499- run_renaming_test (
1500- & ( "macro_rules! inner ( ($e:pat ) => ($e));
1501- macro_rules! outer ( ($e:pat ) => (inner!($e)));
1502- fn main() { let outer!(g) = 13; g;}" ,
1503- vec ! ( vec!( 0 ) ) ,
1504- true ) ,
1505- 0 )
1506- }
1507-
15081398 // create a really evil test case where a $x appears inside a binding of $x
15091399 // but *shouldn't* bind because it was inserted by a different macro....
15101400 // can't write this test case until we have macro-generating macros.
15111401
1512- // method arg hygiene
1513- // method expands to fn get_x(&self_0, x_1: i32) {self_0 + self_2 + x_3 + x_1}
1514- #[ test]
1515- fn method_arg_hygiene ( ) {
1516- run_renaming_test (
1517- & ( "macro_rules! inject_x (()=>(x));
1518- macro_rules! inject_self (()=>(self));
1519- struct A;
1520- impl A{fn get_x(&self, x: i32) {self + inject_self!() + inject_x!() + x;} }" ,
1521- vec ! ( vec!( 0 ) , vec!( 3 ) ) ,
1522- true ) ,
1523- 0 )
1524- }
1525-
1526- // ooh, got another bite?
1527- // expands to struct A; impl A {fn thingy(&self_1) {self_1;}}
1528- #[ test]
1529- fn method_arg_hygiene_2 ( ) {
1530- run_renaming_test (
1531- & ( "struct A;
1532- macro_rules! add_method (($T:ty) =>
1533- (impl $T { fn thingy(&self) {self;} }));
1534- add_method!(A);" ,
1535- vec ! ( vec!( 0 ) ) ,
1536- true ) ,
1537- 0 )
1538- }
1539-
1540- // item fn hygiene
1541- // expands to fn q(x_1: i32){fn g(x_2: i32){x_2 + x_1};}
1542- #[ test]
1543- fn issue_9383 ( ) {
1544- run_renaming_test (
1545- & ( "macro_rules! bad_macro (($ex:expr) => (fn g(x: i32){ x + $ex }));
1546- fn q(x: i32) { bad_macro!(x); }" ,
1547- vec ! ( vec!( 1 ) , vec!( 0 ) ) , true ) ,
1548- 0 )
1549- }
1550-
1551- // closure arg hygiene (ExprKind::Closure)
1552- // expands to fn f(){(|x_1 : i32| {(x_2 + x_1)})(3);}
1553- #[ test]
1554- fn closure_arg_hygiene ( ) {
1555- run_renaming_test (
1556- & ( "macro_rules! inject_x (()=>(x));
1557- fn f(){(|x : i32| {(inject_x!() + x)})(3);}" ,
1558- vec ! ( vec!( 1 ) ) ,
1559- true ) ,
1560- 0 )
1561- }
1562-
1563- // macro_rules in method position. Sadly, unimplemented.
1564- #[ test]
1565- fn macro_in_method_posn ( ) {
1566- expand_crate_str (
1567- "macro_rules! my_method (() => (fn thirteen(&self) -> i32 {13}));
1568- struct A;
1569- impl A{ my_method!(); }
1570- fn f(){A.thirteen;}" . to_string ( ) ) ;
1571- }
1572-
1573- // another nested macro
1574- // expands to impl Entries {fn size_hint(&self_1) {self_1;}
1575- #[ test]
1576- fn item_macro_workaround ( ) {
1577- run_renaming_test (
1578- & ( "macro_rules! item { ($i:item) => {$i}}
1579- struct Entries;
1580- macro_rules! iterator_impl {
1581- () => { item!( impl Entries { fn size_hint(&self) { self;}});}}
1582- iterator_impl! { }" ,
1583- vec ! ( vec!( 0 ) ) , true ) ,
1584- 0 )
1585- }
1586-
1587- // run one of the renaming tests
1588- fn run_renaming_test ( t : & RenamingTest , test_idx : usize ) {
1589- let invalid_name = keywords:: Invalid . name ( ) ;
1590- let ( teststr, bound_connections, bound_ident_check) = match * t {
1591- ( ref str, ref conns, bic) => ( str. to_string ( ) , conns. clone ( ) , bic)
1592- } ;
1593- let cr = expand_crate_str ( teststr. to_string ( ) ) ;
1594- let bindings = crate_bindings ( & cr) ;
1595- let varrefs = crate_varrefs ( & cr) ;
1596-
1597- // must be one check clause for each binding:
1598- assert_eq ! ( bindings. len( ) , bound_connections. len( ) ) ;
1599- for ( binding_idx, shouldmatch) in bound_connections. iter ( ) . enumerate ( ) {
1600- let binding_name = mtwt:: resolve ( bindings[ binding_idx] ) ;
1601- let binding_marks = mtwt:: marksof ( bindings[ binding_idx] . ctxt , invalid_name) ;
1602- // shouldmatch can't name varrefs that don't exist:
1603- assert ! ( ( shouldmatch. is_empty( ) ) ||
1604- ( varrefs. len( ) > * shouldmatch. iter( ) . max( ) . unwrap( ) ) ) ;
1605- for ( idx, varref) in varrefs. iter ( ) . enumerate ( ) {
1606- let print_hygiene_debug_info = || {
1607- // good lord, you can't make a path with 0 segments, can you?
1608- let final_varref_ident = match varref. segments . last ( ) {
1609- Some ( pathsegment) => pathsegment. identifier ,
1610- None => panic ! ( "varref with 0 path segments?" )
1611- } ;
1612- let varref_name = mtwt:: resolve ( final_varref_ident) ;
1613- let varref_idents : Vec < ast:: Ident >
1614- = varref. segments . iter ( ) . map ( |s| s. identifier )
1615- . collect ( ) ;
1616- println ! ( "varref #{}: {:?}, resolves to {}" , idx, varref_idents, varref_name) ;
1617- println ! ( "varref's first segment's string: \" {}\" " , final_varref_ident) ;
1618- println ! ( "binding #{}: {}, resolves to {}" ,
1619- binding_idx, bindings[ binding_idx] , binding_name) ;
1620- mtwt:: with_sctable ( |x| mtwt:: display_sctable ( x) ) ;
1621- } ;
1622- if shouldmatch. contains ( & idx) {
1623- // it should be a path of length 1, and it should
1624- // be free-identifier=? or bound-identifier=? to the given binding
1625- assert_eq ! ( varref. segments. len( ) , 1 ) ;
1626- let varref_name = mtwt:: resolve ( varref. segments [ 0 ] . identifier ) ;
1627- let varref_marks = mtwt:: marksof ( varref. segments [ 0 ]
1628- . identifier
1629- . ctxt ,
1630- invalid_name) ;
1631- if !( varref_name==binding_name) {
1632- println ! ( "uh oh, should match but doesn't:" ) ;
1633- print_hygiene_debug_info ( ) ;
1634- }
1635- assert_eq ! ( varref_name, binding_name) ;
1636- if bound_ident_check {
1637- // we're checking bound-identifier=?, and the marks
1638- // should be the same, too:
1639- assert_eq ! ( varref_marks, binding_marks. clone( ) ) ;
1640- }
1641- } else {
1642- let varref_name = mtwt:: resolve ( varref. segments [ 0 ] . identifier ) ;
1643- let fail = ( varref. segments . len ( ) == 1 )
1644- && ( varref_name == binding_name) ;
1645- // temp debugging:
1646- if fail {
1647- println ! ( "failure on test {}" , test_idx) ;
1648- println ! ( "text of test case: \" {}\" " , teststr) ;
1649- println ! ( "" ) ;
1650- println ! ( "uh oh, matches but shouldn't:" ) ;
1651- print_hygiene_debug_info ( ) ;
1652- }
1653- assert ! ( !fail) ;
1654- }
1655- }
1656- }
1657- }
1658-
16591402 #[ test]
16601403 fn fmt_in_macro_used_inside_module_macro ( ) {
16611404 let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()));
0 commit comments