@@ -29,7 +29,13 @@ const REPAIR_TEMP_STEP: f64 = 0.10;
2929/// Multi-module projects get more iterations since failures are often localized.
3030fn effective_max_repairs ( interface_count : usize , c_loc : u32 ) -> u32 {
3131 let module_bonus = ( interface_count / 3 ) as u32 ;
32- let size_bonus = if c_loc > 2000 { 2 } else if c_loc > 1000 { 1 } else { 0 } ;
32+ let size_bonus = if c_loc > 2000 {
33+ 2
34+ } else if c_loc > 1000 {
35+ 1
36+ } else {
37+ 0
38+ } ;
3339 ( BASE_REPAIR_ITERATIONS + module_bonus + size_bonus) . min ( MAX_REPAIR_ITERATIONS )
3440}
3541
@@ -83,16 +89,10 @@ fn discover_projects(dataset_path: &Path) -> Result<Vec<CrustProject>> {
8389 let rbench = dataset_path. join ( "RBench" ) ;
8490
8591 if !cbench. is_dir ( ) {
86- anyhow:: bail!(
87- "CBench directory not found at {}" ,
88- cbench. display( )
89- ) ;
92+ anyhow:: bail!( "CBench directory not found at {}" , cbench. display( ) ) ;
9093 }
9194 if !rbench. is_dir ( ) {
92- anyhow:: bail!(
93- "RBench directory not found at {}" ,
94- rbench. display( )
95- ) ;
95+ anyhow:: bail!( "RBench directory not found at {}" , rbench. display( ) ) ;
9696 }
9797
9898 let mut rbench_names: std:: collections:: HashMap < String , PathBuf > =
@@ -141,8 +141,8 @@ fn read_c_sources(cbench_dir: &Path) -> Result<String> {
141141 let mut combined = String :: new ( ) ;
142142 for path in & sources {
143143 let name = path. strip_prefix ( cbench_dir) . unwrap_or ( path) ;
144- let content = std :: fs :: read_to_string ( path )
145- . with_context ( || format ! ( "reading {}" , path. display( ) ) ) ?;
144+ let content =
145+ std :: fs :: read_to_string ( path ) . with_context ( || format ! ( "reading {}" , path. display( ) ) ) ?;
146146 combined. push_str ( & format ! ( "// === {} ===\n " , name. display( ) ) ) ;
147147 combined. push_str ( & content) ;
148148 combined. push_str ( "\n \n " ) ;
@@ -633,7 +633,13 @@ fn write_and_read_impls(
633633 read_current_impls ( workdir, interface_files)
634634}
635635
636- fn make_error_result ( name : String , c_loc : u32 , start : std:: time:: Instant , llm_calls : u32 , error : String ) -> ProjectResult {
636+ fn make_error_result (
637+ name : String ,
638+ c_loc : u32 ,
639+ start : std:: time:: Instant ,
640+ llm_calls : u32 ,
641+ error : String ,
642+ ) -> ProjectResult {
637643 ProjectResult {
638644 name,
639645 c_loc,
@@ -721,7 +727,13 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
721727 ) ;
722728
723729 match client
724- . run_prompt ( & module_model, TRANSLATION_PREAMBLE , 0.3 , module_tokens, & module_prompt)
730+ . run_prompt (
731+ & module_model,
732+ TRANSLATION_PREAMBLE ,
733+ 0.3 ,
734+ module_tokens,
735+ & module_prompt,
736+ )
725737 . await
726738 {
727739 Ok ( response) => {
@@ -760,7 +772,13 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
760772 }
761773 }
762774 Err ( e) => {
763- return make_error_result ( name, c_loc, start, 1 , format ! ( "translation failed: {e}" ) ) ;
775+ return make_error_result (
776+ name,
777+ c_loc,
778+ start,
779+ 1 ,
780+ format ! ( "translation failed: {e}" ) ,
781+ ) ;
764782 }
765783 }
766784 }
@@ -785,13 +803,26 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
785803 let temp = 0.3 + ( iter as f64 - 1.0 ) * REPAIR_TEMP_STEP ;
786804
787805 let repair_prompt = build_repair_prompt (
788- & c_source, & interface_files, & current_impl, & last_errors,
789- iter, max_repairs,
806+ & c_source,
807+ & interface_files,
808+ & current_impl,
809+ & last_errors,
810+ iter,
811+ max_repairs,
790812 ) ;
791813
792814 info ! ( project = %name, iteration = iter, max = max_repairs, temp, "repair attempt (build)" ) ;
793815
794- match client. run_prompt ( & repair_model, REPAIR_PREAMBLE , temp, max_tokens, & repair_prompt) . await {
816+ match client
817+ . run_prompt (
818+ & repair_model,
819+ REPAIR_PREAMBLE ,
820+ temp,
821+ max_tokens,
822+ & repair_prompt,
823+ )
824+ . await
825+ {
795826 Ok ( response) => {
796827 llm_calls += 1 ;
797828 let repaired = parse_multi_file_output ( & response, & interface_files) ;
@@ -838,22 +869,43 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
838869 let temp = 0.3 + ( iter as f64 - 1.0 ) * REPAIR_TEMP_STEP ;
839870
840871 // Use targeted repair if we have per-binary failure info
841- let failed_only: Vec < _ > = failed_binaries. iter ( ) . filter ( |b| !b. passed ) . cloned ( ) . collect ( ) ;
872+ let failed_only: Vec < _ > = failed_binaries
873+ . iter ( )
874+ . filter ( |b| !b. passed )
875+ . cloned ( )
876+ . collect ( ) ;
842877 let repair_prompt = if !failed_only. is_empty ( ) {
843878 build_targeted_repair_prompt (
844- & c_source, & interface_files, & current_impl,
845- & failed_only, iter, max_repairs,
879+ & c_source,
880+ & interface_files,
881+ & current_impl,
882+ & failed_only,
883+ iter,
884+ max_repairs,
846885 )
847886 } else {
848887 build_repair_prompt (
849- & c_source, & interface_files, & current_impl,
850- & test_out, iter, max_repairs,
888+ & c_source,
889+ & interface_files,
890+ & current_impl,
891+ & test_out,
892+ iter,
893+ max_repairs,
851894 )
852895 } ;
853896
854897 info ! ( project = %name, iteration = iter, max = max_repairs, temp, "repair attempt (tests)" ) ;
855898
856- match client. run_prompt ( & repair_model, REPAIR_PREAMBLE , temp, max_tokens, & repair_prompt) . await {
899+ match client
900+ . run_prompt (
901+ & repair_model,
902+ REPAIR_PREAMBLE ,
903+ temp,
904+ max_tokens,
905+ & repair_prompt,
906+ )
907+ . await
908+ {
857909 Ok ( response) => {
858910 llm_calls += 1 ;
859911 let repaired = parse_multi_file_output ( & response, & interface_files) ;
@@ -894,13 +946,23 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
894946 let unsafe_count = count_unsafe ( & current_impl) ;
895947 let idiomatic_score = if compilation_success {
896948 let base = 100.0_f64 - ( unsafe_count as f64 * 10.0 ) ;
897- if tests_passed { base. max ( 0.0 ) } else { ( base * 0.5 ) . max ( 0.0 ) }
949+ if tests_passed {
950+ base. max ( 0.0 )
951+ } else {
952+ ( base * 0.5 ) . max ( 0.0 )
953+ }
898954 } else {
899955 0.0
900956 } ;
901957
902958 let elapsed = start. elapsed ( ) . as_millis ( ) as u64 ;
903- let status = if tests_passed { "PASS" } else if compilation_success { "BUILD_OK" } else { "FAIL" } ;
959+ let status = if tests_passed {
960+ "PASS"
961+ } else if compilation_success {
962+ "BUILD_OK"
963+ } else {
964+ "FAIL"
965+ } ;
904966 info ! ( project = %name, status, c_loc, rust_loc, unsafe_count, repair_iterations, llm_calls, elapsed_ms = elapsed, "project complete" ) ;
905967
906968 ProjectResult {
@@ -915,7 +977,11 @@ async fn run_project(project: &CrustProject, config: &MigrationConfig) -> Projec
915977 repair_iterations,
916978 llm_calls,
917979 total_ms : elapsed,
918- error : if compilation_success { None } else { Some ( last_errors) } ,
980+ error : if compilation_success {
981+ None
982+ } else {
983+ Some ( last_errors)
984+ } ,
919985 }
920986}
921987
@@ -953,7 +1019,13 @@ pub async fn run_crust_bench(config: &CrustBenchConfig) -> Result<CrustBenchRepo
9531019 for ( i, project) in projects. iter ( ) . enumerate ( ) {
9541020 info ! ( project = %project. name, progress = format!( "[{}/{}]" , i + 1 , projects. len( ) ) , "starting project" ) ;
9551021 let result = run_project ( project, & config. migration_config ) . await ;
956- let status = if result. tests_passed { "PASS" } else if result. compilation_success { "BUILD_OK" } else { "FAIL" } ;
1022+ let status = if result. tests_passed {
1023+ "PASS"
1024+ } else if result. compilation_success {
1025+ "BUILD_OK"
1026+ } else {
1027+ "FAIL"
1028+ } ;
9571029 info ! ( project = %result. name, status, score = format!( "{:.0}" , result. idiomatic_score_avg) , llm_calls = result. llm_calls, time_ms = result. total_ms, progress = format!( "[{}/{}]" , i + 1 , projects. len( ) ) , "completed project" ) ;
9581030 results. push ( result) ;
9591031 }
@@ -969,12 +1041,23 @@ pub async fn run_crust_bench(config: &CrustBenchConfig) -> Result<CrustBenchRepo
9691041 let total_llm_calls: u32 = results. iter ( ) . map ( |r| r. llm_calls ) . sum ( ) ;
9701042 let total_repair_iterations: u32 = results. iter ( ) . map ( |r| r. repair_iterations ) . sum ( ) ;
9711043
972- info ! ( total, compiled, passed, total_llm_calls, "CRUST-Bench evaluation complete" ) ;
1044+ info ! (
1045+ total,
1046+ compiled, passed, total_llm_calls, "CRUST-Bench evaluation complete"
1047+ ) ;
9731048
9741049 Ok ( CrustBenchReport {
9751050 total_projects : total,
976- compilation_rate : if total > 0 { compiled as f64 / total as f64 } else { 0.0 } ,
977- test_pass_rate : if total > 0 { passed as f64 / total as f64 } else { 0.0 } ,
1051+ compilation_rate : if total > 0 {
1052+ compiled as f64 / total as f64
1053+ } else {
1054+ 0.0
1055+ } ,
1056+ test_pass_rate : if total > 0 {
1057+ passed as f64 / total as f64
1058+ } else {
1059+ 0.0
1060+ } ,
9781061 avg_idiomatic_score : avg_score,
9791062 total_llm_calls,
9801063 total_repair_iterations,
@@ -1049,10 +1132,14 @@ mod tests {
10491132
10501133 #[ test]
10511134 fn test_build_single_module_prompt ( ) {
1052- let target = ( PathBuf :: from ( "src/interfaces/foo.rs" ) , "fn foo() { unimplemented!() }" . to_string ( ) ) ;
1053- let others = vec ! [
1054- ( PathBuf :: from( "src/interfaces/bar.rs" ) , "fn bar() -> i32 { 42 }" . to_string( ) ) ,
1055- ] ;
1135+ let target = (
1136+ PathBuf :: from ( "src/interfaces/foo.rs" ) ,
1137+ "fn foo() { unimplemented!() }" . to_string ( ) ,
1138+ ) ;
1139+ let others = vec ! [ (
1140+ PathBuf :: from( "src/interfaces/bar.rs" ) ,
1141+ "fn bar() -> i32 { 42 }" . to_string( ) ,
1142+ ) ] ;
10561143 let prompt = build_single_module_prompt ( "int foo() { return 1; }" , & target, & others) ;
10571144 assert ! ( prompt. contains( "Target: implement foo.rs" ) ) ;
10581145 assert ! ( prompt. contains( "Other module interfaces" ) ) ;
@@ -1063,14 +1150,20 @@ mod tests {
10631150 fn test_select_module_model_haiku ( ) {
10641151 let config = MigrationConfig :: default ( ) ;
10651152 let model = select_module_model ( 50 , & config) ;
1066- assert ! ( model. contains( "haiku" ) , "small module should use Haiku: {model}" ) ;
1153+ assert ! (
1154+ model. contains( "haiku" ) ,
1155+ "small module should use Haiku: {model}"
1156+ ) ;
10671157 }
10681158
10691159 #[ test]
10701160 fn test_select_module_model_sonnet ( ) {
10711161 let config = MigrationConfig :: default ( ) ;
10721162 let model = select_module_model ( 200 , & config) ;
1073- assert ! ( model. contains( "sonnet" ) , "medium module should use Sonnet: {model}" ) ;
1163+ assert ! (
1164+ model. contains( "sonnet" ) ,
1165+ "medium module should use Sonnet: {model}"
1166+ ) ;
10741167 }
10751168
10761169 #[ test]
0 commit comments