Skip to content

Commit e85f09f

Browse files
committed
bootstrap: emit hint if a config key is used in the wrong section
1 parent 52618eb commit e85f09f

File tree

2 files changed

+67
-15
lines changed

2 files changed

+67
-15
lines changed

src/bootstrap/Cargo.lock

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -662,18 +662,27 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
662662

663663
[[package]]
664664
name = "serde"
665-
version = "1.0.215"
665+
version = "1.0.224"
666666
source = "registry+https://github.com/rust-lang/crates.io-index"
667-
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
667+
checksum = "6aaeb1e94f53b16384af593c71e20b095e958dab1d26939c1b70645c5cfbcc0b"
668+
dependencies = [
669+
"serde_core",
670+
]
671+
672+
[[package]]
673+
name = "serde_core"
674+
version = "1.0.224"
675+
source = "registry+https://github.com/rust-lang/crates.io-index"
676+
checksum = "32f39390fa6346e24defbcdd3d9544ba8a19985d0af74df8501fbfe9a64341ab"
668677
dependencies = [
669678
"serde_derive",
670679
]
671680

672681
[[package]]
673682
name = "serde_derive"
674-
version = "1.0.215"
683+
version = "1.0.224"
675684
source = "registry+https://github.com/rust-lang/crates.io-index"
676-
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
685+
checksum = "87ff78ab5e8561c9a675bfc1785cb07ae721f0ee53329a595cefd8c04c2ac4e0"
677686
dependencies = [
678687
"proc-macro2",
679688
"quote",

src/bootstrap/src/core/config/config.rs

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)