66use std:: cell:: { Cell , RefCell } ;
77use std:: collections:: { BTreeSet , HashMap , HashSet } ;
88use std:: fmt:: { self , Display } ;
9+ use std:: hash:: Hash ;
910use std:: io:: IsTerminal ;
1011use std:: path:: { Path , PathBuf , absolute} ;
1112use std:: process:: Command ;
@@ -745,19 +746,25 @@ enum ReplaceOpt {
745746}
746747
747748trait 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
751757impl 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
914930impl < 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