@@ -1265,7 +1265,7 @@ mod tests {
1265
1265
use ext:: mtwt;
1266
1266
use fold:: Folder ;
1267
1267
use parse;
1268
- use parse:: token:: { self , keywords } ;
1268
+ use parse:: token;
1269
1269
use util:: parser_testing:: { string_to_parser} ;
1270
1270
use util:: parser_testing:: { string_to_pat, string_to_crate, strs_to_idents} ;
1271
1271
use visit;
@@ -1395,267 +1395,10 @@ mod tests {
1395
1395
) ;
1396
1396
}
1397
1397
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
-
1508
1398
// create a really evil test case where a $x appears inside a binding of $x
1509
1399
// but *shouldn't* bind because it was inserted by a different macro....
1510
1400
// can't write this test case until we have macro-generating macros.
1511
1401
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
-
1659
1402
#[ test]
1660
1403
fn fmt_in_macro_used_inside_module_macro ( ) {
1661
1404
let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()));
0 commit comments