Cargo custom subcommand lookup is kind of weird

I've found it weird that cargo will look first in ~/.cargo/bin for custom subcommands. If I run /my/path/to/a/toolchain/install/bin/cargo clippy, I would expect, I think, for /my/path/to/a/toolchain/install/bin/cargo-clippy to be higher priority than ~/.cargo/bin/cargo-clippy, which will invoke whatever the default toolchain managed by rustup is.

I also don't love that ~/.cargo/bin is higher priority than PATH - it makes it impossible to override the subcommands installed in ~/.cargo/bin.

Is this behavior intentional?

I would hope so: this makes it easy to override provided versions with custom ones when you need to do so, even on machines on which you have no root/administrator rights.

You already have the ability to override system binaries by putting ~/.local/bin first in your PATH, though.

What if cargo was changed to prepend dirname(argv[0]) and ~/.cargo/bin to PATH, in that order, if and only if each is not already present, and then do all its subcommand lookups via PATH? That would give /my/path/to/a/toolchain/install/bin/ priority when the cargo in that directory is invoked as such, reproduce the current behavior when it isn't, and allow the user to override both these things by editing their PATH.

What if cargo was changed to prepend dirname(argv[0])

Ah, this isn't exactly what I want. I was just trying to indicate where my cargo is located. It's most likely to be invoked by name via PATH.

I think there are two things here:

  • It's weird that custom subcommands that are all but built-in like cargo-clippy and cargo-fmt bind less tightly than those commands which are actually built-in.
  • It's weird that a hardcoded path supersedes the PATH variable. That seems backwards to me.

Maybe it's just me, but having to actually make file system changes to use custom versions of built-in subcommands is more disruptive than changing the PATH variable to use the custom command.

The reason this is coming up is because I prefer to use a Rust toolchain installed via a third-party package manager, but will occasionally use rustup for one-off toolchain tests. But then this overrides cargo-clippy and cargo-fmt, which gives me unexpected behavior when I use my usual toolchain.