rust-lang / rust-lang/rust-clippy
New lint: `interchangeable_params` flag functions where 2+ params share the same type
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
What it does
Flags function signatures where two or more parameters share the same type, making them silently swappable at the call site without any compiler warning.
Advantage
- Catches bugs the type system completely ignores
- Forces better API design at the signature level
- The exceptions are narrow enough that what's left flagged is genuinely ambiguous
- Pure static analysis, no runtime cost, no overhead
Drawbacks
No response
Example
// bad — three IDs and four money values, all swappable within their type
fn process_order_payout(
shop_id: String,
customer_id: String,
order_id: String,
amount: i64,
platform_fee: i64,
tx_fee: i64,
net_amount: i64,
) {}
// compiles, pays the wrong entity the wrong amount
process_order_payout(customer_id, shop_id, order_id, net_amount, tx_fee, platform_fee, amount);
Could be written as:
// fix — newtypes make each parameter distinct
struct ShopId(String);
struct CustomerId(String);
struct OrderId(String);
struct Amount(i64);
struct PlatformFee(i64);
struct TxFee(i64);
struct NetAmount(i64);
fn process_order_payout(
shop_id: ShopId,
customer_id: CustomerId,
order_id: OrderId,
amount: Amount,
platform_fee: PlatformFee,
tx_fee: TxFee,
net_amount: NetAmount,
) {}
// or use a struct to group them
struct OrderPayoutParams {
shop_id: ShopId,
customer_id: CustomerId,
order_id: OrderId,
amount: Amount,
platform_fee: PlatformFee,
tx_fee: TxFee,
net_amount: NetAmount,
}
fn process_order_payout(params: OrderPayoutParams) {}
The compiler only sees types. Two String params are indistinguishable at the call site. A swap compiles, passes review, ships to prod, and breaks in a way that looks like perfectly valid code.
Exceptions
- Known positional conventions:
x, y, z,a, b,lhs, rhs - Operator trait impls:
fn eq(&self, other: &Self) - Functions with only 2 params where names clearly convey order
- Closure arguments
- Trait implementations where the signature is fixed by the trait
Comparison with existing lints
too_many_argumentsflags functions with too many parameters but doesn't care whether the types are interchangeable. A function with 8 parameters of 8 distinct types is fine from a swappability perspective.- This lint is orthogonal: even a 2-parameter function like
fn transfer(from: String, to: String)is dangerous if both params share a type.
Additional Context
I wrote about this in detail here: https://sot.dev/everything-should-be-typed.html
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No source file or test is named. Start by locating the existing too_many_arguments lint and its tests in rust-clippy, then compare their registration and exception handling with the proposed rules. Done means the new lint is registered, flags the stated interchangeable-parameter cases, skips the listed exceptions, and has coverage for representative examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100