6
6
use std:: cell:: { Cell , RefCell } ;
7
7
use std:: collections:: { BTreeSet , HashMap , HashSet } ;
8
8
use std:: fmt:: { self , Display } ;
9
+ use std:: hash:: Hash ;
9
10
use std:: io:: IsTerminal ;
10
11
use std:: path:: { Path , PathBuf , absolute} ;
11
12
use std:: process:: Command ;
@@ -745,19 +746,25 @@ enum ReplaceOpt {
745
746
}
746
747
747
748
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
+ ) ;
749
755
}
750
756
751
757
impl Merge for TomlConfig {
752
758
fn merge (
753
759
& mut self ,
760
+ included_extensions : & mut HashSet < PathBuf > ,
754
761
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include } : Self ,
755
762
replace : ReplaceOpt ,
756
763
) {
757
764
fn do_merge < T : Merge > ( x : & mut Option < T > , y : Option < T > , replace : ReplaceOpt ) {
758
765
if let Some ( new) = y {
759
766
if let Some ( original) = x {
760
- original. merge ( new, replace) ;
767
+ original. merge ( & mut Default :: default ( ) , new, replace) ;
761
768
} else {
762
769
* x = Some ( new) ;
763
770
}
@@ -772,11 +779,20 @@ impl Merge for TomlConfig {
772
779
) ;
773
780
exit ! ( 2 ) ;
774
781
} ) ;
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) ;
776
792
}
777
793
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) ;
780
796
781
797
do_merge ( & mut self . build , build, replace) ;
782
798
do_merge ( & mut self . install , install, replace) ;
@@ -791,7 +807,7 @@ impl Merge for TomlConfig {
791
807
( Some ( original_target) , Some ( new_target) ) => {
792
808
for ( triple, new) in new_target {
793
809
if let Some ( original) = original_target. get_mut ( & triple) {
794
- original. merge ( new, replace) ;
810
+ original. merge ( & mut Default :: default ( ) , new, replace) ;
795
811
} else {
796
812
original_target. insert ( triple, new) ;
797
813
}
@@ -812,7 +828,7 @@ macro_rules! define_config {
812
828
}
813
829
814
830
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 ) {
816
832
$(
817
833
match replace {
818
834
ReplaceOpt :: IgnoreDuplicate => {
@@ -912,7 +928,12 @@ macro_rules! define_config {
912
928
}
913
929
914
930
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
+ ) {
916
937
match replace {
917
938
ReplaceOpt :: IgnoreDuplicate => {
918
939
if self . is_none ( ) {
@@ -1608,7 +1629,7 @@ impl Config {
1608
1629
) ;
1609
1630
exit ! ( 2 ) ;
1610
1631
} ) ;
1611
- toml. merge ( included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
1632
+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
1612
1633
}
1613
1634
1614
1635
for include_path in toml. include . clone ( ) . unwrap_or_default ( ) {
@@ -1619,7 +1640,7 @@ impl Config {
1619
1640
) ;
1620
1641
exit ! ( 2 ) ;
1621
1642
} ) ;
1622
- toml. merge ( included_toml, ReplaceOpt :: Override ) ;
1643
+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: Override ) ;
1623
1644
}
1624
1645
1625
1646
let mut override_toml = TomlConfig :: default ( ) ;
@@ -1630,7 +1651,7 @@ impl Config {
1630
1651
1631
1652
let mut err = match get_table ( option) {
1632
1653
Ok ( v) => {
1633
- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1654
+ override_toml. merge ( & mut Default :: default ( ) , v, ReplaceOpt :: ErrorOnDuplicate ) ;
1634
1655
continue ;
1635
1656
}
1636
1657
Err ( e) => e,
@@ -1641,7 +1662,11 @@ impl Config {
1641
1662
if !value. contains ( '"' ) {
1642
1663
match get_table ( & format ! ( r#"{key}="{value}""# ) ) {
1643
1664
Ok ( v) => {
1644
- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1665
+ override_toml. merge (
1666
+ & mut Default :: default ( ) ,
1667
+ v,
1668
+ ReplaceOpt :: ErrorOnDuplicate ,
1669
+ ) ;
1645
1670
continue ;
1646
1671
}
1647
1672
Err ( e) => err = e,
@@ -1651,7 +1676,7 @@ impl Config {
1651
1676
eprintln ! ( "failed to parse override `{option}`: `{err}" ) ;
1652
1677
exit ! ( 2 )
1653
1678
}
1654
- toml. merge ( override_toml, ReplaceOpt :: Override ) ;
1679
+ toml. merge ( & mut Default :: default ( ) , override_toml, ReplaceOpt :: Override ) ;
1655
1680
1656
1681
config. change_id = toml. change_id . inner ;
1657
1682
0 commit comments