@@ -1644,6 +1644,48 @@ impl Config {
1644
1644
/// as a path.
1645
1645
fn get_tool ( & self , tool : & str , from_config : & Option < ConfigRelativePath > ) -> PathBuf {
1646
1646
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
+ } )
1647
1689
. unwrap_or_else ( || PathBuf :: from ( tool) )
1648
1690
}
1649
1691
0 commit comments