@@ -206,7 +206,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate) -> ast::Crate {
206206 } ) ,
207207 path : Vec :: new ( ) ,
208208 testfns : Vec :: new ( ) ,
209- reexport_mod_ident : token:: str_to_ident ( "__test_reexports" ) ,
209+ reexport_mod_ident : token:: gensym_ident ( "__test_reexports" ) ,
210210 is_test_crate : is_test_crate ( & krate) ,
211211 config : krate. config . clone ( ) ,
212212 } ;
@@ -384,7 +384,7 @@ fn mk_test_module(cx: &TestCtxt) -> Gc<ast::Item> {
384384 let item_ = ast:: ItemMod ( testmod) ;
385385
386386 let item = ast:: Item {
387- ident : token:: str_to_ident ( "__test" ) ,
387+ ident : token:: gensym_ident ( "__test" ) ,
388388 attrs : Vec :: new ( ) ,
389389 id : ast:: DUMMY_NODE_ID ,
390390 node : item_,
@@ -417,11 +417,27 @@ fn mk_tests(cx: &TestCtxt) -> Gc<ast::Item> {
417417 // The vector of test_descs for this crate
418418 let test_descs = mk_test_descs ( cx) ;
419419
420- ( quote_item ! ( & cx. ext_cx,
421- pub static TESTS : & ' static [ self :: test:: TestDescAndFn ] =
422- $test_descs
423- ;
424- ) ) . unwrap ( )
420+ // FIXME #15962: should be using quote_item, but that stringifies
421+ // __test_reexports, causing it to be reinterned, losing the
422+ // gensym information.
423+ let sp = DUMMY_SP ;
424+ let ecx = & cx. ext_cx ;
425+ let struct_type = ecx. ty_path ( ecx. path ( sp, vec ! [ ecx. ident_of( "self" ) ,
426+ ecx. ident_of( "test" ) ,
427+ ecx. ident_of( "TestDescAndFn" ) ] ) ,
428+ None ) ;
429+ let static_lt = ecx. lifetime ( sp, token:: special_idents:: static_lifetime. name ) ;
430+ // &'static [self::test::TestDescAndFn]
431+ let static_type = ecx. ty_rptr ( sp,
432+ ecx. ty ( sp, ast:: TyVec ( struct_type) ) ,
433+ Some ( static_lt) ,
434+ ast:: MutImmutable ) ;
435+ // static TESTS: $static_type = &[...];
436+ ecx. item_static ( sp,
437+ ecx. ident_of ( "TESTS" ) ,
438+ static_type,
439+ ast:: MutImmutable ,
440+ test_descs)
425441}
426442
427443fn is_test_crate ( krate : & ast:: Crate ) -> bool {
@@ -448,59 +464,58 @@ fn mk_test_descs(cx: &TestCtxt) -> Gc<ast::Expr> {
448464}
449465
450466fn mk_test_desc_and_fn_rec ( cx : & TestCtxt , test : & Test ) -> Gc < ast:: Expr > {
467+ // FIXME #15962: should be using quote_expr, but that stringifies
468+ // __test_reexports, causing it to be reinterned, losing the
469+ // gensym information.
470+
451471 let span = test. span ;
452472 let path = test. path . clone ( ) ;
473+ let ecx = & cx. ext_cx ;
474+ let self_id = ecx. ident_of ( "self" ) ;
475+ let test_id = ecx. ident_of ( "test" ) ;
476+
477+ // creates self::test::$name
478+ let test_path = |name| {
479+ ecx. path ( span, vec ! [ self_id, test_id, ecx. ident_of( name) ] )
480+ } ;
481+ // creates $name: $expr
482+ let field = |name, expr| ecx. field_imm ( span, ecx. ident_of ( name) , expr) ;
453483
454484 debug ! ( "encoding {}" , ast_util:: path_name_i( path. as_slice( ) ) ) ;
455485
456- let name_lit: ast:: Lit =
457- nospan ( ast:: LitStr ( token:: intern_and_get_ident (
458- ast_util:: path_name_i ( path. as_slice ( ) ) . as_slice ( ) ) ,
459- ast:: CookedStr ) ) ;
486+ // path to the #[test] function: "foo::bar::baz"
487+ let path_string = ast_util:: path_name_i ( path. as_slice ( ) ) ;
488+ let name_expr = ecx. expr_str ( span, token:: intern_and_get_ident ( path_string. as_slice ( ) ) ) ;
460489
461- let name_expr = box ( GC ) ast:: Expr {
462- id : ast:: DUMMY_NODE_ID ,
463- node : ast:: ExprLit ( box ( GC ) name_lit) ,
464- span : span
465- } ;
490+ // self::test::StaticTestName($name_expr)
491+ let name_expr = ecx. expr_call ( span,
492+ ecx. expr_path ( test_path ( "StaticTestName" ) ) ,
493+ vec ! [ name_expr] ) ;
466494
467- let mut visible_path = vec ! [ cx. reexport_mod_ident. clone( ) ] ;
468- visible_path. extend ( path. move_iter ( ) ) ;
469- let fn_path = cx. ext_cx . path_global ( DUMMY_SP , visible_path) ;
495+ let ignore_expr = ecx. expr_bool ( span, test. ignore ) ;
496+ let fail_expr = ecx. expr_bool ( span, test. should_fail ) ;
470497
471- let fn_expr = box ( GC ) ast:: Expr {
472- id : ast:: DUMMY_NODE_ID ,
473- node : ast:: ExprPath ( fn_path) ,
474- span : span,
475- } ;
498+ // self::test::TestDesc { ... }
499+ let desc_expr = ecx. expr_struct (
500+ span,
501+ test_path ( "TestDesc" ) ,
502+ vec ! [ field( "name" , name_expr) ,
503+ field( "ignore" , ignore_expr) ,
504+ field( "should_fail" , fail_expr) ] ) ;
476505
477- let t_expr = if test. bench {
478- quote_expr ! ( & cx. ext_cx, self :: test:: StaticBenchFn ( $fn_expr) )
479- } else {
480- quote_expr ! ( & cx. ext_cx, self :: test:: StaticTestFn ( $fn_expr) )
481- } ;
482506
483- let ignore_expr = if test. ignore {
484- quote_expr ! ( & cx. ext_cx, true )
485- } else {
486- quote_expr ! ( & cx. ext_cx, false )
487- } ;
507+ let mut visible_path = vec ! [ cx. reexport_mod_ident. clone( ) ] ;
508+ visible_path. extend ( path. move_iter ( ) ) ;
488509
489- let fail_expr = if test. should_fail {
490- quote_expr ! ( & cx. ext_cx, true )
491- } else {
492- quote_expr ! ( & cx. ext_cx, false )
493- } ;
510+ let fn_expr = ecx. expr_path ( ecx. path_global ( span, visible_path) ) ;
494511
495- let e = quote_expr ! ( & cx. ext_cx,
496- self :: test:: TestDescAndFn {
497- desc: self :: test:: TestDesc {
498- name: self :: test:: StaticTestName ( $name_expr) ,
499- ignore: $ignore_expr,
500- should_fail: $fail_expr
501- } ,
502- testfn: $t_expr,
503- }
504- ) ;
505- e
512+ let variant_name = if test. bench { "StaticBenchFn" } else { "StaticTestFn" } ;
513+ // self::test::$variant_name($fn_expr)
514+ let testfn_expr = ecx. expr_call ( span, ecx. expr_path ( test_path ( variant_name) ) , vec ! [ fn_expr] ) ;
515+
516+ // self::test::TestDescAndFn { ... }
517+ ecx. expr_struct ( span,
518+ test_path ( "TestDescAndFn" ) ,
519+ vec ! [ field( "desc" , desc_expr) ,
520+ field( "testfn" , testfn_expr) ] )
506521}
0 commit comments