@@ -567,10 +567,36 @@ impl Cfg {
567
567
return Ok ( Some ( ( name. into ( ) , reason) ) ) ;
568
568
}
569
569
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) ?;
574
600
if let Some ( toolchain_name) = & override_file. toolchain . channel {
575
601
let all_toolchains = self . list_toolchains ( ) ?;
576
602
if !all_toolchains. iter ( ) . any ( |s| s == toolchain_name) {
@@ -590,12 +616,15 @@ impl Cfg {
590
616
Ok ( None )
591
617
}
592
618
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 > {
594
623
let contents = contents. as_ref ( ) ;
595
624
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 ) => {
599
628
let channel = contents. trim ( ) ;
600
629
601
630
if channel. is_empty ( ) {
@@ -898,6 +927,20 @@ impl Cfg {
898
927
}
899
928
}
900
929
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
+
901
944
#[ cfg( test) ]
902
945
mod tests {
903
946
use super :: * ;
@@ -906,7 +949,7 @@ mod tests {
906
949
fn parse_legacy_toolchain_file ( ) {
907
950
let contents = "nightly-2020-07-10" ;
908
951
909
- let result = Cfg :: parse_override_file ( contents) ;
952
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
910
953
assert_eq ! (
911
954
result. unwrap( ) ,
912
955
OverrideFile {
@@ -929,7 +972,7 @@ targets = [ "wasm32-unknown-unknown", "thumbv2-none-eabi" ]
929
972
profile = "default"
930
973
"# ;
931
974
932
- let result = Cfg :: parse_override_file ( contents) ;
975
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
933
976
assert_eq ! (
934
977
result. unwrap( ) ,
935
978
OverrideFile {
@@ -952,7 +995,7 @@ profile = "default"
952
995
channel = "nightly-2020-07-10"
953
996
"# ;
954
997
955
- let result = Cfg :: parse_override_file ( contents) ;
998
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
956
999
assert_eq ! (
957
1000
result. unwrap( ) ,
958
1001
OverrideFile {
@@ -973,7 +1016,7 @@ channel = "nightly-2020-07-10"
973
1016
components = []
974
1017
"# ;
975
1018
976
- let result = Cfg :: parse_override_file ( contents) ;
1019
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
977
1020
assert_eq ! (
978
1021
result. unwrap( ) ,
979
1022
OverrideFile {
@@ -994,7 +1037,7 @@ channel = "nightly-2020-07-10"
994
1037
targets = []
995
1038
"# ;
996
1039
997
- let result = Cfg :: parse_override_file ( contents) ;
1040
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
998
1041
assert_eq ! (
999
1042
result. unwrap( ) ,
1000
1043
OverrideFile {
@@ -1014,7 +1057,7 @@ targets = []
1014
1057
components = [ "rustfmt" ]
1015
1058
"# ;
1016
1059
1017
- let result = Cfg :: parse_override_file ( contents) ;
1060
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
1018
1061
assert_eq ! (
1019
1062
result. unwrap( ) ,
1020
1063
OverrideFile {
@@ -1034,7 +1077,7 @@ components = [ "rustfmt" ]
1034
1077
[toolchain]
1035
1078
"# ;
1036
1079
1037
- let result = Cfg :: parse_override_file ( contents) ;
1080
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
1038
1081
assert ! ( matches!(
1039
1082
result. unwrap_err( ) . kind( ) ,
1040
1083
ErrorKind :: InvalidOverrideFile
@@ -1045,7 +1088,7 @@ components = [ "rustfmt" ]
1045
1088
fn parse_empty_toolchain_file ( ) {
1046
1089
let contents = "" ;
1047
1090
1048
- let result = Cfg :: parse_override_file ( contents) ;
1091
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
1049
1092
assert ! ( matches!(
1050
1093
result. unwrap_err( ) . kind( ) ,
1051
1094
ErrorKind :: EmptyOverrideFile
@@ -1056,7 +1099,7 @@ components = [ "rustfmt" ]
1056
1099
fn parse_whitespace_toolchain_file ( ) {
1057
1100
let contents = " " ;
1058
1101
1059
- let result = Cfg :: parse_override_file ( contents) ;
1102
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
1060
1103
assert ! ( matches!(
1061
1104
result. unwrap_err( ) . kind( ) ,
1062
1105
ErrorKind :: EmptyOverrideFile
@@ -1069,7 +1112,7 @@ components = [ "rustfmt" ]
1069
1112
channel = nightly
1070
1113
"# ;
1071
1114
1072
- let result = Cfg :: parse_override_file ( contents) ;
1115
+ let result = Cfg :: parse_override_file ( contents, ParseMode :: Both ) ;
1073
1116
assert ! ( matches!(
1074
1117
result. unwrap_err( ) . kind( ) ,
1075
1118
ErrorKind :: ParsingOverrideFile ( ..)
0 commit comments