@@ -1911,6 +1911,7 @@ fn run_rustdoc_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
19111911}
19121912
19131913fn run_codegen_units_test ( config : & Config , props : & TestProps , testpaths : & TestPaths ) {
1914+
19141915 assert ! ( props. revisions. is_empty( ) , "revisions not relevant here" ) ;
19151916
19161917 let proc_res = compile_test ( config, props, testpaths) ;
@@ -1921,36 +1922,148 @@ fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPa
19211922
19221923 check_no_compiler_crash ( None , & proc_res) ;
19231924
1924- let prefix = "TRANS_ITEM " ;
1925+ const PREFIX : & ' static str = "TRANS_ITEM " ;
1926+ const CGU_MARKER : & ' static str = "@@" ;
19251927
1926- let actual: HashSet < String > = proc_res
1928+ let actual: Vec < TransItem > = proc_res
19271929 . stdout
19281930 . lines ( )
1929- . filter ( |line| line. starts_with ( prefix ) )
1930- . map ( |s| ( & s [ prefix . len ( ) .. ] ) . to_string ( ) )
1931+ . filter ( |line| line. starts_with ( PREFIX ) )
1932+ . map ( str_to_trans_item )
19311933 . collect ( ) ;
19321934
1933- let expected: HashSet < String > = errors:: load_errors ( & testpaths. file , None )
1935+ let expected: Vec < TransItem > = errors:: load_errors ( & testpaths. file , None )
19341936 . iter ( )
1935- . map ( |e| e. msg . trim ( ) . to_string ( ) )
1937+ . map ( |e| str_to_trans_item ( & e. msg [ .. ] ) )
19361938 . collect ( ) ;
19371939
1938- if actual != expected {
1939- let mut missing: Vec < _ > = expected. difference ( & actual) . collect ( ) ;
1940+ let mut missing = Vec :: new ( ) ;
1941+ let mut wrong_cgus = Vec :: new ( ) ;
1942+
1943+ for expected_item in & expected {
1944+ let actual_item_with_same_name = actual. iter ( )
1945+ . find ( |ti| ti. name == expected_item. name ) ;
1946+
1947+ if let Some ( actual_item) = actual_item_with_same_name {
1948+ if !expected_item. codegen_units . is_empty ( ) {
1949+ // Also check for codegen units
1950+ if expected_item. codegen_units != actual_item. codegen_units {
1951+ wrong_cgus. push ( ( expected_item. clone ( ) , actual_item. clone ( ) ) ) ;
1952+ }
1953+ }
1954+ } else {
1955+ missing. push ( expected_item. string . clone ( ) ) ;
1956+ }
1957+ }
1958+
1959+ let unexpected: Vec < _ > =
1960+ actual. iter ( )
1961+ . filter ( |acgu| !expected. iter ( ) . any ( |ecgu| acgu. name == ecgu. name ) )
1962+ . map ( |acgu| acgu. string . clone ( ) )
1963+ . collect ( ) ;
1964+
1965+ if !missing. is_empty ( ) {
19401966 missing. sort ( ) ;
19411967
1942- let mut too_much: Vec < _ > = actual. difference ( & expected) . collect ( ) ;
1943- too_much. sort ( ) ;
1968+ println ! ( "\n These items should have been contained but were not:\n " ) ;
1969+
1970+ for item in & missing {
1971+ println ! ( "{}" , item) ;
1972+ }
19441973
1945- println ! ( "Expected and actual sets of codegen-items differ.\n \
1946- These items should have been contained but were not:\n \n \
1947- {}\n \n \
1948- These items were contained but should not have been:\n \n \
1949- {}\n \n ",
1950- missing. iter( ) . fold( "" . to_string( ) , |s1, s2| s1 + "\n " + s2) ,
1951- too_much. iter( ) . fold( "" . to_string( ) , |s1, s2| s1 + "\n " + s2) ) ;
1974+ println ! ( "\n " ) ;
1975+ }
1976+
1977+ if !unexpected. is_empty ( ) {
1978+ let sorted = {
1979+ let mut sorted = unexpected. clone ( ) ;
1980+ sorted. sort ( ) ;
1981+ sorted
1982+ } ;
1983+
1984+ println ! ( "\n These items were contained but should not have been:\n " ) ;
1985+
1986+ for item in sorted {
1987+ println ! ( "{}" , item) ;
1988+ }
1989+
1990+ println ! ( "\n " ) ;
1991+ }
1992+
1993+ if !wrong_cgus. is_empty ( ) {
1994+ wrong_cgus. sort_by_key ( |pair| pair. 0 . name . clone ( ) ) ;
1995+ println ! ( "\n The following items were assigned to wrong codegen units:\n " ) ;
1996+
1997+ for & ( ref expected_item, ref actual_item) in & wrong_cgus {
1998+ println ! ( "{}" , expected_item. name) ;
1999+ println ! ( " expected: {}" , codegen_units_to_str( & expected_item. codegen_units) ) ;
2000+ println ! ( " actual: {}" , codegen_units_to_str( & actual_item. codegen_units) ) ;
2001+ println ! ( "" ) ;
2002+ }
2003+ }
2004+
2005+ if !( missing. is_empty ( ) && unexpected. is_empty ( ) && wrong_cgus. is_empty ( ) )
2006+ {
19522007 panic ! ( ) ;
19532008 }
2009+
2010+ #[ derive( Clone , Eq , PartialEq ) ]
2011+ struct TransItem {
2012+ name : String ,
2013+ codegen_units : HashSet < String > ,
2014+ string : String ,
2015+ }
2016+
2017+ // [TRANS_ITEM] name [@@ (cgu)+]
2018+ fn str_to_trans_item ( s : & str ) -> TransItem {
2019+ let s = if s. starts_with ( PREFIX ) {
2020+ ( & s[ PREFIX . len ( ) ..] ) . trim ( )
2021+ } else {
2022+ s. trim ( )
2023+ } ;
2024+
2025+ let full_string = format ! ( "{}{}" , PREFIX , s. trim( ) . to_owned( ) ) ;
2026+
2027+ let parts: Vec < & str > = s. split ( CGU_MARKER )
2028+ . map ( str:: trim)
2029+ . filter ( |s| !s. is_empty ( ) )
2030+ . collect ( ) ;
2031+
2032+ let name = parts[ 0 ] . trim ( ) ;
2033+
2034+ let cgus = if parts. len ( ) > 1 {
2035+ let cgus_str = parts[ 1 ] ;
2036+
2037+ cgus_str. split ( " " )
2038+ . map ( str:: trim)
2039+ . filter ( |s| !s. is_empty ( ) )
2040+ . map ( str:: to_owned)
2041+ . collect ( )
2042+ }
2043+ else {
2044+ HashSet :: new ( )
2045+ } ;
2046+
2047+ TransItem {
2048+ name : name. to_owned ( ) ,
2049+ codegen_units : cgus,
2050+ string : full_string,
2051+ }
2052+ }
2053+
2054+ fn codegen_units_to_str ( cgus : & HashSet < String > ) -> String
2055+ {
2056+ let mut cgus: Vec < _ > = cgus. iter ( ) . collect ( ) ;
2057+ cgus. sort ( ) ;
2058+
2059+ let mut string = String :: new ( ) ;
2060+ for cgu in cgus {
2061+ string. push_str ( & cgu[ ..] ) ;
2062+ string. push_str ( " " ) ;
2063+ }
2064+
2065+ string
2066+ }
19542067}
19552068
19562069fn run_incremental_test ( config : & Config , props : & TestProps , testpaths : & TestPaths ) {
0 commit comments