@@ -1644,6 +1644,48 @@ impl Config {
16441644 /// as a path.
16451645 fn get_tool ( & self , tool : & str , from_config : & Option < ConfigRelativePath > ) -> PathBuf {
16461646 self . maybe_get_tool ( tool, from_config)
1647+ . or_else ( || {
1648+ // This is an optimization to circumvent the rustup proxies
1649+ // which can have a significant performance hit. The goal here
1650+ // is to determine if calling `rustc` from PATH would end up
1651+ // calling the proxies.
1652+ //
1653+ // This is somewhat cautious trying to determine if it is safe
1654+ // to circumvent rustup, because there are some situations
1655+ // where users may do things like modify PATH, call cargo
1656+ // directly, use a custom rustup toolchain link without a
1657+ // cargo executable, etc. However, there is still some risk
1658+ // this may make the wrong decision in unusual circumstances.
1659+ //
1660+ // First, we must be running under rustup in the first place.
1661+ let toolchain = self . get_env_os ( "RUSTUP_TOOLCHAIN" ) ?;
1662+ // If the tool on PATH is the same as `rustup` on path, then
1663+ // there is pretty good evidence that it will be a proxy.
1664+ let tool_resolved = paths:: resolve_executable ( Path :: new ( tool) ) . ok ( ) ?;
1665+ let rustup_resolved = paths:: resolve_executable ( Path :: new ( "rustup" ) ) . ok ( ) ?;
1666+ let tool_meta = tool_resolved. metadata ( ) . ok ( ) ?;
1667+ let rustup_meta = rustup_resolved. metadata ( ) . ok ( ) ?;
1668+ // This works on the assumption that rustup and its proxies
1669+ // use hard links to a single binary. If rustup ever changes
1670+ // that setup, then I think the worst consequence is that this
1671+ // optimization will not work, and it will take the slow path.
1672+ if tool_meta. len ( ) != rustup_meta. len ( ) {
1673+ return None ;
1674+ }
1675+ // Try to find the tool in rustup's toolchain directory.
1676+ let tool_exe = Path :: new ( tool) . with_extension ( env:: consts:: EXE_EXTENSION ) ;
1677+ let toolchain_exe = home:: rustup_home ( )
1678+ . ok ( ) ?
1679+ . join ( "toolchains" )
1680+ . join ( & toolchain)
1681+ . join ( "bin" )
1682+ . join ( & tool_exe) ;
1683+ if toolchain_exe. exists ( ) {
1684+ Some ( toolchain_exe)
1685+ } else {
1686+ None
1687+ }
1688+ } )
16471689 . unwrap_or_else ( || PathBuf :: from ( tool) )
16481690 }
16491691
0 commit comments