@@ -600,7 +600,8 @@ impl Target {
600600#[ serde( deny_unknown_fields, rename_all = "kebab-case" ) ]
601601pub ( crate ) struct TomlConfig {
602602 changelog_seen : Option < usize > , // FIXME: Deprecated field. Remove it at 2024.
603- change_id : Option < usize > ,
603+ #[ serde( flatten) ]
604+ change_id : ChangeIdWrapper ,
604605 build : Option < Build > ,
605606 install : Option < Install > ,
606607 llvm : Option < Llvm > ,
@@ -610,6 +611,16 @@ pub(crate) struct TomlConfig {
610611 profile : Option < String > ,
611612}
612613
614+ /// Since we use `#[serde(deny_unknown_fields)]` on `TomlConfig`, we need a wrapper type
615+ /// for the "change-id" field to parse it even if other fields are invalid. This ensures
616+ /// that if deserialization fails due to other fields, we can still provide the changelogs
617+ /// to allow developers to potentially find the reason for the failure in the logs..
618+ #[ derive( Deserialize , Default ) ]
619+ pub ( crate ) struct ChangeIdWrapper {
620+ #[ serde( alias = "change-id" ) ]
621+ inner : Option < usize > ,
622+ }
623+
613624/// Describes how to handle conflicts in merging two [`TomlConfig`]
614625#[ derive( Copy , Clone , Debug ) ]
615626enum ReplaceOpt {
@@ -651,7 +662,7 @@ impl Merge for TomlConfig {
651662 }
652663 }
653664 self . changelog_seen . merge ( changelog_seen, replace) ;
654- self . change_id . merge ( change_id, replace) ;
665+ self . change_id . inner . merge ( change_id. inner , replace) ;
655666 do_merge ( & mut self . build , build, replace) ;
656667 do_merge ( & mut self . install , install, replace) ;
657668 do_merge ( & mut self . llvm , llvm, replace) ;
@@ -1200,6 +1211,20 @@ impl Config {
12001211 toml:: from_str ( & contents)
12011212 . and_then ( |table : toml:: Value | TomlConfig :: deserialize ( table) )
12021213 . unwrap_or_else ( |err| {
1214+ if let Ok ( Some ( changes) ) = toml:: from_str ( & contents)
1215+ . and_then ( |table : toml:: Value | ChangeIdWrapper :: deserialize ( table) )
1216+ . and_then ( |change_id| {
1217+ Ok ( change_id. inner . map ( |id| crate :: find_recent_config_change_ids ( id) ) )
1218+ } )
1219+ {
1220+ if !changes. is_empty ( ) {
1221+ println ! (
1222+ "WARNING: There have been changes to x.py since you last updated:\n {}" ,
1223+ crate :: human_readable_changes( & changes)
1224+ ) ;
1225+ }
1226+ }
1227+
12031228 eprintln ! ( "failed to parse TOML configuration '{}': {err}" , file. display( ) ) ;
12041229 exit ! ( 2 ) ;
12051230 } )
@@ -1366,7 +1391,7 @@ impl Config {
13661391 toml. merge ( override_toml, ReplaceOpt :: Override ) ;
13671392
13681393 config. changelog_seen = toml. changelog_seen ;
1369- config. change_id = toml. change_id ;
1394+ config. change_id = toml. change_id . inner ;
13701395
13711396 let Build {
13721397 build,
0 commit comments