11use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
22use std:: path:: { Path , PathBuf } ;
33use std:: sync:: Arc ;
4- use std:: { env, fs} ;
4+ use std:: { env, fmt , fs} ;
55
66use crate :: core:: compiler:: { CompileKind , DefaultExecutor , Executor , UnitOutput } ;
77use crate :: core:: { Dependency , Edition , Package , PackageId , SourceId , Target , Workspace } ;
@@ -14,6 +14,7 @@ use crate::util::errors::CargoResult;
1414use crate :: util:: { Filesystem , GlobalContext , Rustc } ;
1515use crate :: { drop_println, ops} ;
1616
17+ use annotate_snippets:: Level ;
1718use anyhow:: { Context as _, bail} ;
1819use cargo_util:: paths;
1920use cargo_util_schemas:: core:: PartialVersion ;
@@ -39,6 +40,55 @@ impl Drop for Transaction {
3940 }
4041}
4142
43+ enum RustupToolchainSource {
44+ Default ,
45+ Environment ,
46+ CommandLine ,
47+ OverrideDB ,
48+ ToolchainFile ,
49+ Other ( String ) ,
50+ }
51+
52+ #[ allow( dead_code) ]
53+ impl RustupToolchainSource {
54+ fn is_default ( & self ) -> bool {
55+ matches ! ( self , Self :: Default )
56+ }
57+
58+ fn is_environment_override ( & self ) -> bool {
59+ matches ! ( self , Self :: Environment )
60+ }
61+
62+ fn is_command_line_override ( & self ) -> bool {
63+ matches ! ( self , Self :: CommandLine )
64+ }
65+
66+ fn is_current_dir_override ( & self ) -> bool {
67+ matches ! ( self , Self :: OverrideDB )
68+ }
69+
70+ fn is_toolchain_file_override ( & self ) -> bool {
71+ matches ! ( self , Self :: ToolchainFile )
72+ }
73+
74+ fn is_other_override ( & self ) -> bool {
75+ matches ! ( self , Self :: Other ( _) )
76+ }
77+ }
78+
79+ impl fmt:: Display for RustupToolchainSource {
80+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
81+ f. write_str ( match self {
82+ Self :: Default => "default" ,
83+ Self :: Environment => "env" ,
84+ Self :: CommandLine => "cli" ,
85+ Self :: OverrideDB => "path-override" ,
86+ Self :: ToolchainFile => "toolchain-file" ,
87+ Self :: Other ( other) => other,
88+ } )
89+ }
90+ }
91+
4292struct InstallablePackage < ' gctx > {
4393 gctx : & ' gctx GlobalContext ,
4494 opts : ops:: CompileOptions ,
@@ -316,6 +366,25 @@ impl<'gctx> InstallablePackage<'gctx> {
316366 fn install_one ( mut self , dry_run : bool ) -> CargoResult < bool > {
317367 self . gctx . shell ( ) . status ( "Installing" , & self . pkg ) ?;
318368
369+ if let Some ( source) = self . get_rustup_toolchain_source ( )
370+ && !source. is_default ( )
371+ && !source. is_command_line_override ( )
372+ {
373+ #[ allow( clippy:: disallowed_methods) ]
374+ let maybe_toolchain = env:: var ( "RUSTUP_TOOLCHAIN" )
375+ . ok ( )
376+ . map ( |toolchain| format ! ( " `{toolchain}`" ) )
377+ . unwrap_or_default ( ) ;
378+ let report = & [ Level :: WARNING
379+ . secondary_title ( format ! (
380+ "using non-default toolchain{maybe_toolchain} overridden by {source}"
381+ ) )
382+ . element ( Level :: HELP . message ( format ! (
383+ "use `cargo +stable install` if you meant to use the stable toolchain."
384+ ) ) ) ] ;
385+ self . gctx . shell ( ) . print_report ( report, false ) ?;
386+ }
387+
319388 // Normalize to absolute path for consistency throughout.
320389 // See: https://github.com/rust-lang/cargo/issues/16023
321390 let dst = self . root . join ( "bin" ) . into_path_unlocked ( ) ;
@@ -593,6 +662,20 @@ impl<'gctx> InstallablePackage<'gctx> {
593662 }
594663 }
595664
665+ fn get_rustup_toolchain_source ( & self ) -> Option < RustupToolchainSource > {
666+ #[ allow( clippy:: disallowed_methods) ]
667+ let source = std:: env:: var ( "RUSTUP_TOOLCHAIN_SOURCE" ) . ok ( ) ?;
668+ let source = match source. as_str ( ) {
669+ "default" => RustupToolchainSource :: Default ,
670+ "env" => RustupToolchainSource :: Environment ,
671+ "cli" => RustupToolchainSource :: CommandLine ,
672+ "path-override" => RustupToolchainSource :: OverrideDB ,
673+ "toolchain-file" => RustupToolchainSource :: ToolchainFile ,
674+ other => RustupToolchainSource :: Other ( other. to_owned ( ) ) ,
675+ } ;
676+ Some ( source)
677+ }
678+
596679 fn check_yanked_install ( & self ) -> CargoResult < ( ) > {
597680 if self . ws . ignore_lock ( ) || !self . ws . root ( ) . join ( "Cargo.lock" ) . exists ( ) {
598681 return Ok ( ( ) ) ;
0 commit comments