@@ -420,7 +420,6 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
420
420
span : span
421
421
}
422
422
} ) ;
423
- let fm = fresh_mark ( ) ;
424
423
// mark before expansion:
425
424
let marked_tts = mark_tts ( tts, fm) ;
426
425
let marked_ctxt = new_mark ( fm, ctxt) ;
@@ -1533,7 +1532,7 @@ mod test {
1533
1532
use super :: * ;
1534
1533
use ast;
1535
1534
use ast:: { Attribute_ , AttrOuter , MetaWord , EMPTY_CTXT } ;
1536
- use ast_util:: { get_sctable, mtwt_resolve, new_rename} ;
1535
+ use ast_util:: { get_sctable, mtwt_marksof , mtwt_resolve, new_rename} ;
1537
1536
use codemap;
1538
1537
use codemap:: Spanned ;
1539
1538
use parse;
@@ -1709,31 +1708,40 @@ mod test {
1709
1708
//
1710
1709
// The comparisons are done post-mtwt-resolve, so we're comparing renamed
1711
1710
// names; differences in marks don't matter any more.
1712
- type renaming_test = (&'static str, ~[~[uint]]);
1711
+ //
1712
+ // oog... I also want tests that check " binding-identifier-=?". That is,
1713
+ // not just "do these have the same name", but "do they have the same
1714
+ // name *and* the same marks"? Understanding this is really pretty painful.
1715
+ // in principle, you might want to control this boolean on a per-varref basis,
1716
+ // but that would make things even harder to understand, and might not be
1717
+ // necessary for thorough testing.
1718
+ type renaming_test = ( & ' static str, ~[ ~[ uint] ] , bool) ;
1713
1719
1714
1720
#[ test]
1715
1721
fn automatic_renaming ( ) {
1716
- // need some other way to test these...
1717
1722
let tests : ~[ renaming_test ] =
1718
1723
~[ // b & c should get new names throughout, in the expr too:
1719
1724
( "fn a() -> int { let b = 13; let c = b; b+c }" ,
1720
- ~[~[0,1],~[2]]),
1725
+ ~[ ~[ 0 , 1 ] , ~[ 2 ] ] , false ) ,
1721
1726
// both x's should be renamed (how is this causing a bug?)
1722
1727
( "fn main () {let x : int = 13;x;}" ,
1723
- ~[~[0]]),
1728
+ ~[ ~[ 0 ] ] , false ) ,
1724
1729
// the use of b after the + should be renamed, the other one not:
1725
1730
( "macro_rules! f (($x:ident) => (b + $x)) fn a() -> int { let b = 13; f!(b)}" ,
1726
- ~[~[1]]),
1731
+ ~[ ~[ 1 ] ] , false ) ,
1727
1732
// the b before the plus should not be renamed (requires marks)
1728
1733
( "macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}" ,
1729
- ~[~[1]]),
1734
+ ~[ ~[ 1 ] ] , false ) ,
1730
1735
// the marks going in and out of letty should cancel, allowing that $x to
1731
1736
// capture the one following the semicolon.
1732
1737
// this was an awesome test case, and caught a *lot* of bugs.
1733
1738
( "macro_rules! letty(($x:ident) => (let $x = 15;))
1734
1739
macro_rules! user(($x:ident) => ({letty!($x); $x}))
1735
1740
fn main() -> int {user!(z)}" ,
1736
- ~[~[0]])
1741
+ ~[ ~[ 0 ] ] , false ) ,
1742
+ // can't believe I missed this one : a macro def that refers to a local var:
1743
+ ( "fn main() {let x = 19; macro_rules! getx(()=>(x)); getx!();}" ,
1744
+ ~[ ~[ 0 ] ] , true )
1737
1745
// FIXME #6994: the next string exposes the bug referred to in issue 6994, so I'm
1738
1746
// commenting it out.
1739
1747
// the z flows into and out of two macros (g & f) along one path, and one
@@ -1750,10 +1758,10 @@ mod test {
1750
1758
}
1751
1759
}
1752
1760
1753
-
1761
+ // run one of the renaming tests
1754
1762
fn run_renaming_test ( t : & renaming_test ) {
1755
- let ( teststr, bound_connections) = match * t {
1756
- ( ref str, ref conns) => ( str. to_managed ( ) , conns. clone ( ) )
1763
+ let ( teststr, bound_connections, bound_ident_check ) = match * t {
1764
+ ( ref str, ref conns, bic ) => ( str. to_managed ( ) , conns. clone ( ) , bic )
1757
1765
} ;
1758
1766
let cr = expand_crate_str ( teststr. to_managed ( ) ) ;
1759
1767
// find the bindings:
@@ -1766,15 +1774,18 @@ mod test {
1766
1774
assert_eq ! ( bindings. len( ) , bound_connections. len( ) ) ;
1767
1775
for ( binding_idx, shouldmatch) in bound_connections. iter ( ) . enumerate ( ) {
1768
1776
let binding_name = mtwt_resolve ( bindings[ binding_idx] ) ;
1777
+ let binding_marks = mtwt_marksof ( bindings[ binding_idx] . ctxt , binding_name) ;
1769
1778
// shouldmatch can't name varrefs that don't exist:
1770
1779
assert ! ( ( shouldmatch. len( ) == 0 ) ||
1771
1780
( varrefs. len( ) > * shouldmatch. iter( ) . max( ) . unwrap( ) ) ) ;
1772
1781
for ( idx, varref) in varrefs. iter ( ) . enumerate ( ) {
1773
1782
if shouldmatch. contains ( & idx) {
1774
1783
// it should be a path of length 1, and it should
1775
- // be free-identifier=? to the given binding
1784
+ // be free-identifier=? or bound-identifier=? to the given binding
1776
1785
assert_eq ! ( varref. segments. len( ) , 1 ) ;
1777
1786
let varref_name = mtwt_resolve ( varref. segments [ 0 ] . identifier ) ;
1787
+ let varref_marks = mtwt_marksof ( varref. segments [ 0 ] . identifier . ctxt ,
1788
+ binding_name) ;
1778
1789
if ( !( varref_name==binding_name) ) {
1779
1790
std:: io:: println ( "uh oh, should match but doesn't:" ) ;
1780
1791
std:: io:: println ( fmt ! ( "varref: %?" , varref) ) ;
@@ -1786,6 +1797,10 @@ mod test {
1786
1797
}
1787
1798
}
1788
1799
assert_eq ! ( varref_name, binding_name) ;
1800
+ if ( bound_ident_check) {
1801
+ // we need to check the marks, too:
1802
+ assert_eq ! ( varref_marks, binding_marks. clone( ) ) ;
1803
+ }
1789
1804
} else {
1790
1805
let fail = ( varref. segments . len ( ) == 1 )
1791
1806
&& ( mtwt_resolve ( varref. segments [ 0 ] . identifier ) == binding_name) ;
@@ -1854,6 +1869,46 @@ mod test {
1854
1869
} ;
1855
1870
}
1856
1871
1872
+ #[ test] fn fmt_in_macro_used_inside_module_macro ( ) {
1873
+ let crate_str = @"macro_rules! fmt_wrap ( ( $b: expr) =>( fmt ! ( \" left: %?\" , $b) ) )
1874
+ macro_rules! foo_module ( ( ) => ( mod generated { fn a( ) { let xx = 147 ; fmt_wrap!( xx) ; } } ) )
1875
+ foo_module ! ( )
1876
+ ";
1877
+ let cr = expand_crate_str(crate_str);
1878
+ // find the xx binding
1879
+ let bindings = @mut ~[];
1880
+ visit::walk_crate(&mut new_name_finder(bindings), cr, ());
1881
+ let cxbinds : ~[&ast::Ident] =
1882
+ bindings.iter().filter(|b|{@" xx" == ( ident_to_str ( * b) ) } ) . collect ( ) ;
1883
+ let cxbind = match cxbinds {
1884
+ [ b] => b,
1885
+ _ => fail ! ( "expected just one binding for ext_cx" )
1886
+ } ;
1887
+ let resolved_binding = mtwt_resolve ( * cxbind) ;
1888
+ // find all the xx varrefs:
1889
+ let varrefs = @mut ~[ ] ;
1890
+ visit:: walk_crate ( & mut new_path_finder ( varrefs) , cr, ( ) ) ;
1891
+ // the xx binding should bind all of the xx varrefs:
1892
+ for ( idx, v) in varrefs. iter ( ) . filter ( |p|{ p. segments . len ( ) == 1
1893
+ && ( @"xx" == ( ident_to_str ( & p. segments [ 0 ] . identifier ) ) )
1894
+ } ) . enumerate ( ) {
1895
+ if ( mtwt_resolve ( v. segments [ 0 ] . identifier ) != resolved_binding) {
1896
+ std:: io:: println ( "uh oh, xx binding didn't match xx varref:" ) ;
1897
+ std:: io:: println ( fmt ! ( "this is xx varref # %?" , idx) ) ;
1898
+ std:: io:: println ( fmt ! ( "binding: %?" , cxbind) ) ;
1899
+ std:: io:: println ( fmt ! ( "resolves to: %?" , resolved_binding) ) ;
1900
+ std:: io:: println ( fmt ! ( "varref: %?" , v. segments[ 0 ] . identifier) ) ;
1901
+ std:: io:: println ( fmt ! ( "resolves to: %?" , mtwt_resolve( v. segments[ 0 ] . identifier) ) ) ;
1902
+ let table = get_sctable ( ) ;
1903
+ std:: io:: println ( "SC table:" ) ;
1904
+ for ( idx, val) in table. table . iter ( ) . enumerate ( ) {
1905
+ std:: io:: println ( fmt ! ( "%4u : %?" , idx, val) ) ;
1906
+ }
1907
+ }
1908
+ assert_eq ! ( mtwt_resolve( v. segments[ 0 ] . identifier) , resolved_binding) ;
1909
+ } ;
1910
+ }
1911
+
1857
1912
#[ test]
1858
1913
fn pat_idents ( ) {
1859
1914
let pat = string_to_pat ( @"( a, Foo { x : c @ ( b, 9 ) , y : Bar ( 4 , d) } ) ") ;
0 commit comments