@@ -1853,13 +1853,7 @@ fn load_toml_config(
18531853        }  else  { 
18541854            toml_path. clone ( ) 
18551855        } ) ; 
1856-         ( 
1857-             get_toml ( & toml_path) . unwrap_or_else ( |e| { 
1858-                 eprintln ! ( "ERROR: Failed to parse '{}': {e}" ,  toml_path. display( ) ) ; 
1859-                 exit ! ( 2 ) ; 
1860-             } ) , 
1861-             path, 
1862-         ) 
1856+         ( get_toml ( & toml_path) . unwrap_or_else ( |e| bad_config ( & toml_path,  e) ) ,  path) 
18631857    }  else  { 
18641858        ( TomlConfig :: default ( ) ,  None ) 
18651859    } 
@@ -1892,10 +1886,8 @@ fn postprocess_toml(
18921886            . unwrap ( ) 
18931887            . join ( include_path) ; 
18941888
1895-         let  included_toml = get_toml ( & include_path) . unwrap_or_else ( |e| { 
1896-             eprintln ! ( "ERROR: Failed to parse '{}': {e}" ,  include_path. display( ) ) ; 
1897-             exit ! ( 2 ) ; 
1898-         } ) ; 
1889+         let  included_toml =
1890+             get_toml ( & include_path) . unwrap_or_else ( |e| bad_config ( & include_path,  e) ) ; 
18991891        toml. merge ( 
19001892            Some ( include_path) , 
19011893            & mut  Default :: default ( ) , 
@@ -2398,3 +2390,54 @@ pub(crate) fn read_file_by_commit<'a>(
23982390    git. arg ( "show" ) . arg ( format ! ( "{commit}:{}" ,  file. to_str( ) . unwrap( ) ) ) ; 
23992391    git. run_capture_stdout ( dwn_ctx. exec_ctx ) . stdout ( ) 
24002392} 
2393+ 
2394+ fn  bad_config ( toml_path :  & Path ,  e :  toml:: de:: Error )  -> ! { 
2395+     eprintln ! ( "ERROR: Failed to parse '{}': {e}" ,  toml_path. display( ) ) ; 
2396+     let  e_s = e. to_string ( ) ; 
2397+     if  e_s. contains ( "unknown field" ) 
2398+         && let  Some ( field_name)  = e_s. split ( "`" ) . nth ( 1 ) 
2399+         && let  sections = find_correct_section_for_field ( field_name) 
2400+         && !sections. is_empty ( ) 
2401+     { 
2402+         if  sections. len ( )  == 1  { 
2403+             let  section = sections[ 0 ] ; 
2404+             if  section == "<nesting error>"  { 
2405+                 eprintln ! ( "hint: section name `{field_name}` used as a key within a section" ) ; 
2406+             }  else  if  section == "<top level>"  { 
2407+                 eprintln ! ( "hint: try using `{field_name}` as a top level key" ) ; 
2408+             }  else  { 
2409+                 eprintln ! ( "hint: try moving `{field_name}` to the `{section}` section" ) ; 
2410+             } 
2411+         }  else  { 
2412+             eprintln ! ( 
2413+                 "hint: try moving `{field_name}` to one of the following sections: {sections:?}" 
2414+             ) ; 
2415+         } 
2416+     } 
2417+ 
2418+     exit ! ( 2 ) ; 
2419+ } 
2420+ 
2421+ fn  find_correct_section_for_field ( field_name :  & str )  -> Vec < & ' static  str >  { 
2422+     let  sections = [ "<top level>" ,  "build" ,  "install" ,  "llvm" ,  "gcc" ,  "rust" ,  "dist" ] ; 
2423+     if  sections. contains ( & field_name)  { 
2424+         return  vec ! [ "<nesting error>" ] ; 
2425+     } 
2426+     sections
2427+         . iter ( ) 
2428+         . enumerate ( ) 
2429+         . filter_map ( |( i,  section_name) | { 
2430+             let  dummy_config_str = if  i == 0  { 
2431+                 format ! ( "{field_name} = 0\n " ) 
2432+             }  else  { 
2433+                 format ! ( "{section_name}.{field_name} = 0\n " ) 
2434+             } ; 
2435+             let  is_unknown_field = toml:: from_str :: < toml:: Value > ( & dummy_config_str) 
2436+                 . and_then ( TomlConfig :: deserialize) 
2437+                 . err ( ) 
2438+                 . is_some_and ( |e| e. to_string ( ) . contains ( "unknown field" ) ) ; 
2439+             if  is_unknown_field {  None  }  else  {  Some ( section_name)  } 
2440+         } ) 
2441+         . copied ( ) 
2442+         . collect ( ) 
2443+ } 
0 commit comments