@@ -567,10 +567,36 @@ impl Cfg {
567567 return Ok ( Some ( ( name. into ( ) , reason) ) ) ;
568568 }
569569
570- // Then look for 'rust-toolchain'
571- let toolchain_file = d. join ( "rust-toolchain" ) ;
572- if let Ok ( contents) = utils:: read_file ( "toolchain file" , & toolchain_file) {
573- let override_file = Cfg :: parse_override_file ( contents) ?;
570+ // Then look for 'rust-toolchain' or 'rust-toolchain.toml'
571+ let path_rust_toolchain = d. join ( "rust-toolchain" ) ;
572+ let path_rust_toolchain_toml = d. join ( "rust-toolchain.toml" ) ;
573+
574+ let ( toolchain_file, contents, parse_mode) = match (
575+ utils:: read_file ( "toolchain file" , & path_rust_toolchain) ,
576+ utils:: read_file ( "toolchain file" , & path_rust_toolchain_toml) ,
577+ ) {
578+ ( contents, Err ( _) ) => {
579+ // no `rust-toolchain.toml` exists
580+ ( path_rust_toolchain, contents, ParseMode :: Both )
581+ }
582+ ( Err ( _) , Ok ( contents) ) => {
583+ // only `rust-toolchain.toml` exists
584+ ( path_rust_toolchain_toml, Ok ( contents) , ParseMode :: OnlyToml )
585+ }
586+ ( Ok ( contents) , Ok ( _) ) => {
587+ // both `rust-toolchain` and `rust-toolchain.toml` exist
588+
589+ notify ( Notification :: DuplicateToolchainFile {
590+ rust_toolchain : & path_rust_toolchain,
591+ rust_toolchain_toml : & path_rust_toolchain_toml,
592+ } ) ;
593+
594+ ( path_rust_toolchain, Ok ( contents) , ParseMode :: Both )
595+ }
596+ } ;
597+
598+ if let Ok ( contents) = contents {
599+ let override_file = Cfg :: parse_override_file ( contents, parse_mode) ?;
574600 if let Some ( toolchain_name) = & override_file. toolchain . channel {
575601 let all_toolchains = self . list_toolchains ( ) ?;
576602 if !all_toolchains. iter ( ) . any ( |s| s == toolchain_name) {
@@ -590,12 +616,15 @@ impl Cfg {
590616 Ok ( None )
591617 }
592618
593- fn parse_override_file < S : AsRef < str > > ( contents : S ) -> Result < OverrideFile > {
619+ fn parse_override_file < S : AsRef < str > > (
620+ contents : S ,
621+ parse_mode : ParseMode ,
622+ ) -> Result < OverrideFile > {
594623 let contents = contents. as_ref ( ) ;
595624
596- match contents. lines ( ) . count ( ) {
597- 0 => Err ( ErrorKind :: EmptyOverrideFile . into ( ) ) ,
598- 1 => {
625+ match ( contents. lines ( ) . count ( ) , parse_mode ) {
626+ ( 0 , _ ) => Err ( ErrorKind :: EmptyOverrideFile . into ( ) ) ,
627+ ( 1 , ParseMode :: Both ) => {
599628 let channel = contents. trim ( ) ;
600629
601630 if channel. is_empty ( ) {
@@ -898,6 +927,20 @@ impl Cfg {
898927 }
899928}
900929
930+ /// Specifies how a `rust-toolchain`/`rust-toolchain.toml` configuration file should be parsed.
931+ enum ParseMode {
932+ /// Only permit TOML format in a configuration file.
933+ ///
934+ /// This variant is used for `rust-toolchain.toml` files (with `.toml` extension).
935+ OnlyToml ,
936+ /// Permit both the legacy format (i.e. just the channel name) and the TOML format in
937+ /// a configuration file.
938+ ///
939+ /// This variant is used for `rust-toolchain` files (no file extension) for backwards
940+ /// compatibility.
941+ Both ,
942+ }
943+
901944#[ cfg( test) ]
902945mod tests {
903946 use super :: * ;
@@ -906,7 +949,7 @@ mod tests {
906949 fn parse_legacy_toolchain_file ( ) {
907950 let contents = "nightly-2020-07-10" ;
908951
909- let result = Cfg :: parse_override_file ( contents) ;
952+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
910953 assert_eq ! (
911954 result. unwrap( ) ,
912955 OverrideFile {
@@ -929,7 +972,7 @@ targets = [ "wasm32-unknown-unknown", "thumbv2-none-eabi" ]
929972profile = "default"
930973"# ;
931974
932- let result = Cfg :: parse_override_file ( contents) ;
975+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
933976 assert_eq ! (
934977 result. unwrap( ) ,
935978 OverrideFile {
@@ -952,7 +995,7 @@ profile = "default"
952995channel = "nightly-2020-07-10"
953996"# ;
954997
955- let result = Cfg :: parse_override_file ( contents) ;
998+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
956999 assert_eq ! (
9571000 result. unwrap( ) ,
9581001 OverrideFile {
@@ -973,7 +1016,7 @@ channel = "nightly-2020-07-10"
9731016components = []
9741017"# ;
9751018
976- let result = Cfg :: parse_override_file ( contents) ;
1019+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
9771020 assert_eq ! (
9781021 result. unwrap( ) ,
9791022 OverrideFile {
@@ -994,7 +1037,7 @@ channel = "nightly-2020-07-10"
9941037targets = []
9951038"# ;
9961039
997- let result = Cfg :: parse_override_file ( contents) ;
1040+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
9981041 assert_eq ! (
9991042 result. unwrap( ) ,
10001043 OverrideFile {
@@ -1014,7 +1057,7 @@ targets = []
10141057components = [ "rustfmt" ]
10151058"# ;
10161059
1017- let result = Cfg :: parse_override_file ( contents) ;
1060+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
10181061 assert_eq ! (
10191062 result. unwrap( ) ,
10201063 OverrideFile {
@@ -1034,7 +1077,7 @@ components = [ "rustfmt" ]
10341077[toolchain]
10351078"# ;
10361079
1037- let result = Cfg :: parse_override_file ( contents) ;
1080+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
10381081 assert ! ( matches!(
10391082 result. unwrap_err( ) . kind( ) ,
10401083 ErrorKind :: InvalidOverrideFile
@@ -1045,7 +1088,7 @@ components = [ "rustfmt" ]
10451088 fn parse_empty_toolchain_file ( ) {
10461089 let contents = "" ;
10471090
1048- let result = Cfg :: parse_override_file ( contents) ;
1091+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
10491092 assert ! ( matches!(
10501093 result. unwrap_err( ) . kind( ) ,
10511094 ErrorKind :: EmptyOverrideFile
@@ -1056,7 +1099,7 @@ components = [ "rustfmt" ]
10561099 fn parse_whitespace_toolchain_file ( ) {
10571100 let contents = " " ;
10581101
1059- let result = Cfg :: parse_override_file ( contents) ;
1102+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
10601103 assert ! ( matches!(
10611104 result. unwrap_err( ) . kind( ) ,
10621105 ErrorKind :: EmptyOverrideFile
@@ -1069,7 +1112,7 @@ components = [ "rustfmt" ]
10691112channel = nightly
10701113"# ;
10711114
1072- let result = Cfg :: parse_override_file ( contents) ;
1115+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
10731116 assert ! ( matches!(
10741117 result. unwrap_err( ) . kind( ) ,
10751118 ErrorKind :: ParsingOverrideFile ( ..)
0 commit comments