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 ;
@@ -748,19 +749,25 @@ enum ReplaceOpt {
748
749
}
749
750
750
751
trait Merge {
751
- fn merge ( & mut self , other : Self , replace : ReplaceOpt ) ;
752
+ fn merge (
753
+ & mut self ,
754
+ included_extensions : & mut HashSet < PathBuf > ,
755
+ other : Self ,
756
+ replace : ReplaceOpt ,
757
+ ) ;
752
758
}
753
759
754
760
impl Merge for TomlConfig {
755
761
fn merge (
756
762
& mut self ,
763
+ included_extensions : & mut HashSet < PathBuf > ,
757
764
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include } : Self ,
758
765
replace : ReplaceOpt ,
759
766
) {
760
767
fn do_merge < T : Merge > ( x : & mut Option < T > , y : Option < T > , replace : ReplaceOpt ) {
761
768
if let Some ( new) = y {
762
769
if let Some ( original) = x {
763
- original. merge ( new, replace) ;
770
+ original. merge ( & mut Default :: default ( ) , new, replace) ;
764
771
} else {
765
772
* x = Some ( new) ;
766
773
}
@@ -775,11 +782,20 @@ impl Merge for TomlConfig {
775
782
) ;
776
783
exit ! ( 2 ) ;
777
784
} ) ;
778
- self . merge ( included_toml, ReplaceOpt :: Override ) ;
785
+
786
+ assert ! (
787
+ included_extensions. insert( include_path. clone( ) ) ,
788
+ "Cyclic inclusion detected: '{}' is being included again before its previous inclusion was fully processed." ,
789
+ include_path. display( )
790
+ ) ;
791
+
792
+ self . merge ( included_extensions, included_toml, ReplaceOpt :: Override ) ;
793
+
794
+ included_extensions. remove ( & include_path) ;
779
795
}
780
796
781
- self . change_id . inner . merge ( change_id. inner , replace) ;
782
- self . profile . merge ( profile, replace) ;
797
+ self . change_id . inner . merge ( & mut Default :: default ( ) , change_id. inner , replace) ;
798
+ self . profile . merge ( & mut Default :: default ( ) , profile, replace) ;
783
799
784
800
do_merge ( & mut self . build , build, replace) ;
785
801
do_merge ( & mut self . install , install, replace) ;
@@ -794,7 +810,7 @@ impl Merge for TomlConfig {
794
810
( Some ( original_target) , Some ( new_target) ) => {
795
811
for ( triple, new) in new_target {
796
812
if let Some ( original) = original_target. get_mut ( & triple) {
797
- original. merge ( new, replace) ;
813
+ original. merge ( & mut Default :: default ( ) , new, replace) ;
798
814
} else {
799
815
original_target. insert ( triple, new) ;
800
816
}
@@ -815,7 +831,7 @@ macro_rules! define_config {
815
831
}
816
832
817
833
impl Merge for $name {
818
- fn merge( & mut self , other: Self , replace: ReplaceOpt ) {
834
+ fn merge( & mut self , _included_extensions : & mut HashSet < PathBuf > , other: Self , replace: ReplaceOpt ) {
819
835
$(
820
836
match replace {
821
837
ReplaceOpt :: IgnoreDuplicate => {
@@ -915,7 +931,12 @@ macro_rules! define_config {
915
931
}
916
932
917
933
impl < T > Merge for Option < T > {
918
- fn merge ( & mut self , other : Self , replace : ReplaceOpt ) {
934
+ fn merge (
935
+ & mut self ,
936
+ _included_extensions : & mut HashSet < PathBuf > ,
937
+ other : Self ,
938
+ replace : ReplaceOpt ,
939
+ ) {
919
940
match replace {
920
941
ReplaceOpt :: IgnoreDuplicate => {
921
942
if self . is_none ( ) {
@@ -1609,7 +1630,7 @@ impl Config {
1609
1630
) ;
1610
1631
exit ! ( 2 ) ;
1611
1632
} ) ;
1612
- toml. merge ( included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
1633
+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
1613
1634
}
1614
1635
1615
1636
for include_path in toml. include . clone ( ) . unwrap_or_default ( ) {
@@ -1620,7 +1641,7 @@ impl Config {
1620
1641
) ;
1621
1642
exit ! ( 2 ) ;
1622
1643
} ) ;
1623
- toml. merge ( included_toml, ReplaceOpt :: Override ) ;
1644
+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: Override ) ;
1624
1645
}
1625
1646
1626
1647
let mut override_toml = TomlConfig :: default ( ) ;
@@ -1631,7 +1652,7 @@ impl Config {
1631
1652
1632
1653
let mut err = match get_table ( option) {
1633
1654
Ok ( v) => {
1634
- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1655
+ override_toml. merge ( & mut Default :: default ( ) , v, ReplaceOpt :: ErrorOnDuplicate ) ;
1635
1656
continue ;
1636
1657
}
1637
1658
Err ( e) => e,
@@ -1642,7 +1663,11 @@ impl Config {
1642
1663
if !value. contains ( '"' ) {
1643
1664
match get_table ( & format ! ( r#"{key}="{value}""# ) ) {
1644
1665
Ok ( v) => {
1645
- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1666
+ override_toml. merge (
1667
+ & mut Default :: default ( ) ,
1668
+ v,
1669
+ ReplaceOpt :: ErrorOnDuplicate ,
1670
+ ) ;
1646
1671
continue ;
1647
1672
}
1648
1673
Err ( e) => err = e,
@@ -1652,7 +1677,7 @@ impl Config {
1652
1677
eprintln ! ( "failed to parse override `{option}`: `{err}" ) ;
1653
1678
exit ! ( 2 )
1654
1679
}
1655
- toml. merge ( override_toml, ReplaceOpt :: Override ) ;
1680
+ toml. merge ( & mut Default :: default ( ) , override_toml, ReplaceOpt :: Override ) ;
1656
1681
1657
1682
config. change_id = toml. change_id . inner ;
1658
1683
0 commit comments