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 ;
@@ -748,19 +749,25 @@ enum ReplaceOpt {
748749}
749750
750751trait 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+ ) ;
752758}
753759
754760impl Merge for TomlConfig {
755761 fn merge (
756762 & mut self ,
763+ included_extensions : & mut HashSet < PathBuf > ,
757764 TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include } : Self ,
758765 replace : ReplaceOpt ,
759766 ) {
760767 fn do_merge < T : Merge > ( x : & mut Option < T > , y : Option < T > , replace : ReplaceOpt ) {
761768 if let Some ( new) = y {
762769 if let Some ( original) = x {
763- original. merge ( new, replace) ;
770+ original. merge ( & mut Default :: default ( ) , new, replace) ;
764771 } else {
765772 * x = Some ( new) ;
766773 }
@@ -775,11 +782,20 @@ impl Merge for TomlConfig {
775782 ) ;
776783 exit ! ( 2 ) ;
777784 } ) ;
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) ;
779795 }
780796
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) ;
783799
784800 do_merge ( & mut self . build , build, replace) ;
785801 do_merge ( & mut self . install , install, replace) ;
@@ -794,7 +810,7 @@ impl Merge for TomlConfig {
794810 ( Some ( original_target) , Some ( new_target) ) => {
795811 for ( triple, new) in new_target {
796812 if let Some ( original) = original_target. get_mut ( & triple) {
797- original. merge ( new, replace) ;
813+ original. merge ( & mut Default :: default ( ) , new, replace) ;
798814 } else {
799815 original_target. insert ( triple, new) ;
800816 }
@@ -815,7 +831,7 @@ macro_rules! define_config {
815831 }
816832
817833 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 ) {
819835 $(
820836 match replace {
821837 ReplaceOpt :: IgnoreDuplicate => {
@@ -915,7 +931,12 @@ macro_rules! define_config {
915931}
916932
917933impl < 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+ ) {
919940 match replace {
920941 ReplaceOpt :: IgnoreDuplicate => {
921942 if self . is_none ( ) {
@@ -1609,7 +1630,7 @@ impl Config {
16091630 ) ;
16101631 exit ! ( 2 ) ;
16111632 } ) ;
1612- toml. merge ( included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
1633+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: IgnoreDuplicate ) ;
16131634 }
16141635
16151636 for include_path in toml. include . clone ( ) . unwrap_or_default ( ) {
@@ -1620,7 +1641,7 @@ impl Config {
16201641 ) ;
16211642 exit ! ( 2 ) ;
16221643 } ) ;
1623- toml. merge ( included_toml, ReplaceOpt :: Override ) ;
1644+ toml. merge ( & mut Default :: default ( ) , included_toml, ReplaceOpt :: Override ) ;
16241645 }
16251646
16261647 let mut override_toml = TomlConfig :: default ( ) ;
@@ -1631,7 +1652,7 @@ impl Config {
16311652
16321653 let mut err = match get_table ( option) {
16331654 Ok ( v) => {
1634- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1655+ override_toml. merge ( & mut Default :: default ( ) , v, ReplaceOpt :: ErrorOnDuplicate ) ;
16351656 continue ;
16361657 }
16371658 Err ( e) => e,
@@ -1642,7 +1663,11 @@ impl Config {
16421663 if !value. contains ( '"' ) {
16431664 match get_table ( & format ! ( r#"{key}="{value}""# ) ) {
16441665 Ok ( v) => {
1645- override_toml. merge ( v, ReplaceOpt :: ErrorOnDuplicate ) ;
1666+ override_toml. merge (
1667+ & mut Default :: default ( ) ,
1668+ v,
1669+ ReplaceOpt :: ErrorOnDuplicate ,
1670+ ) ;
16461671 continue ;
16471672 }
16481673 Err ( e) => err = e,
@@ -1652,7 +1677,7 @@ impl Config {
16521677 eprintln ! ( "failed to parse override `{option}`: `{err}" ) ;
16531678 exit ! ( 2 )
16541679 }
1655- toml. merge ( override_toml, ReplaceOpt :: Override ) ;
1680+ toml. merge ( & mut Default :: default ( ) , override_toml, ReplaceOpt :: Override ) ;
16561681
16571682 config. change_id = toml. change_id . inner ;
16581683
0 commit comments