@@ -600,7 +600,8 @@ impl Target {
600
600
#[ serde( deny_unknown_fields, rename_all = "kebab-case" ) ]
601
601
pub ( crate ) struct TomlConfig {
602
602
changelog_seen : Option < usize > , // FIXME: Deprecated field. Remove it at 2024.
603
- change_id : Option < usize > ,
603
+ #[ serde( flatten) ]
604
+ change_id : ChangeIdWrapper ,
604
605
build : Option < Build > ,
605
606
install : Option < Install > ,
606
607
llvm : Option < Llvm > ,
@@ -610,6 +611,16 @@ pub(crate) struct TomlConfig {
610
611
profile : Option < String > ,
611
612
}
612
613
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
+
613
624
/// Describes how to handle conflicts in merging two [`TomlConfig`]
614
625
#[ derive( Copy , Clone , Debug ) ]
615
626
enum ReplaceOpt {
@@ -651,7 +662,7 @@ impl Merge for TomlConfig {
651
662
}
652
663
}
653
664
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) ;
655
666
do_merge ( & mut self . build , build, replace) ;
656
667
do_merge ( & mut self . install , install, replace) ;
657
668
do_merge ( & mut self . llvm , llvm, replace) ;
@@ -1200,6 +1211,20 @@ impl Config {
1200
1211
toml:: from_str ( & contents)
1201
1212
. and_then ( |table : toml:: Value | TomlConfig :: deserialize ( table) )
1202
1213
. 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 :: into_human_readable_changes( & changes)
1224
+ ) ;
1225
+ }
1226
+ }
1227
+
1203
1228
eprintln ! ( "failed to parse TOML configuration '{}': {err}" , file. display( ) ) ;
1204
1229
exit ! ( 2 ) ;
1205
1230
} )
@@ -1366,7 +1391,7 @@ impl Config {
1366
1391
toml. merge ( override_toml, ReplaceOpt :: Override ) ;
1367
1392
1368
1393
config. changelog_seen = toml. changelog_seen ;
1369
- config. change_id = toml. change_id ;
1394
+ config. change_id = toml. change_id . inner ;
1370
1395
1371
1396
let Build {
1372
1397
build,
0 commit comments