Skip to content

Commit eb37a3e

Browse files
committed
implement cyclic inclusion handling
Signed-off-by: onur-ozkan <[email protected]>
1 parent 48a1103 commit eb37a3e

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

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

+38-13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use std::cell::{Cell, RefCell};
77
use std::collections::{BTreeSet, HashMap, HashSet};
88
use std::fmt::{self, Display};
9+
use std::hash::Hash;
910
use std::io::IsTerminal;
1011
use std::path::{Path, PathBuf, absolute};
1112
use std::process::Command;
@@ -745,19 +746,25 @@ enum ReplaceOpt {
745746
}
746747

747748
trait Merge {
748-
fn merge(&mut self, other: Self, replace: ReplaceOpt);
749+
fn merge(
750+
&mut self,
751+
included_extensions: &mut HashSet<PathBuf>,
752+
other: Self,
753+
replace: ReplaceOpt,
754+
);
749755
}
750756

751757
impl Merge for TomlConfig {
752758
fn merge(
753759
&mut self,
760+
included_extensions: &mut HashSet<PathBuf>,
754761
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include }: Self,
755762
replace: ReplaceOpt,
756763
) {
757764
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
758765
if let Some(new) = y {
759766
if let Some(original) = x {
760-
original.merge(new, replace);
767+
original.merge(&mut Default::default(), new, replace);
761768
} else {
762769
*x = Some(new);
763770
}
@@ -772,11 +779,20 @@ impl Merge for TomlConfig {
772779
);
773780
exit!(2);
774781
});
775-
self.merge(included_toml, ReplaceOpt::Override);
782+
783+
assert!(
784+
included_extensions.insert(include_path.clone()),
785+
"Cyclic inclusion detected: '{}' is being included again before its previous inclusion was fully processed.",
786+
include_path.display()
787+
);
788+
789+
self.merge(included_extensions, included_toml, ReplaceOpt::Override);
790+
791+
included_extensions.remove(&include_path);
776792
}
777793

778-
self.change_id.inner.merge(change_id.inner, replace);
779-
self.profile.merge(profile, replace);
794+
self.change_id.inner.merge(&mut Default::default(), change_id.inner, replace);
795+
self.profile.merge(&mut Default::default(), profile, replace);
780796

781797
do_merge(&mut self.build, build, replace);
782798
do_merge(&mut self.install, install, replace);
@@ -791,7 +807,7 @@ impl Merge for TomlConfig {
791807
(Some(original_target), Some(new_target)) => {
792808
for (triple, new) in new_target {
793809
if let Some(original) = original_target.get_mut(&triple) {
794-
original.merge(new, replace);
810+
original.merge(&mut Default::default(), new, replace);
795811
} else {
796812
original_target.insert(triple, new);
797813
}
@@ -812,7 +828,7 @@ macro_rules! define_config {
812828
}
813829

814830
impl Merge for $name {
815-
fn merge(&mut self, other: Self, replace: ReplaceOpt) {
831+
fn merge(&mut self, _included_extensions: &mut HashSet<PathBuf>, other: Self, replace: ReplaceOpt) {
816832
$(
817833
match replace {
818834
ReplaceOpt::IgnoreDuplicate => {
@@ -912,7 +928,12 @@ macro_rules! define_config {
912928
}
913929

914930
impl<T> Merge for Option<T> {
915-
fn merge(&mut self, other: Self, replace: ReplaceOpt) {
931+
fn merge(
932+
&mut self,
933+
_included_extensions: &mut HashSet<PathBuf>,
934+
other: Self,
935+
replace: ReplaceOpt,
936+
) {
916937
match replace {
917938
ReplaceOpt::IgnoreDuplicate => {
918939
if self.is_none() {
@@ -1608,7 +1629,7 @@ impl Config {
16081629
);
16091630
exit!(2);
16101631
});
1611-
toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
1632+
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::IgnoreDuplicate);
16121633
}
16131634

16141635
for include_path in toml.include.clone().unwrap_or_default() {
@@ -1619,7 +1640,7 @@ impl Config {
16191640
);
16201641
exit!(2);
16211642
});
1622-
toml.merge(included_toml, ReplaceOpt::Override);
1643+
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::Override);
16231644
}
16241645

16251646
let mut override_toml = TomlConfig::default();
@@ -1630,7 +1651,7 @@ impl Config {
16301651

16311652
let mut err = match get_table(option) {
16321653
Ok(v) => {
1633-
override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
1654+
override_toml.merge(&mut Default::default(), v, ReplaceOpt::ErrorOnDuplicate);
16341655
continue;
16351656
}
16361657
Err(e) => e,
@@ -1641,7 +1662,11 @@ impl Config {
16411662
if !value.contains('"') {
16421663
match get_table(&format!(r#"{key}="{value}""#)) {
16431664
Ok(v) => {
1644-
override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
1665+
override_toml.merge(
1666+
&mut Default::default(),
1667+
v,
1668+
ReplaceOpt::ErrorOnDuplicate,
1669+
);
16451670
continue;
16461671
}
16471672
Err(e) => err = e,
@@ -1651,7 +1676,7 @@ impl Config {
16511676
eprintln!("failed to parse override `{option}`: `{err}");
16521677
exit!(2)
16531678
}
1654-
toml.merge(override_toml, ReplaceOpt::Override);
1679+
toml.merge(&mut Default::default(), override_toml, ReplaceOpt::Override);
16551680

16561681
config.change_id = toml.change_id.inner;
16571682

0 commit comments

Comments
 (0)