Skip to content

Conversation

@borngraced
Copy link

@borngraced borngraced commented Nov 23, 2025

Clippy should warn when a const, static, or let binding is defined as one integer type but immediately/ consistently cast to another type at usage sites without any usage of the original type. fixes #16137

changelog: [needless_type_cast ]: suggests defining bindings as their cast type

@rustbot rustbot added needs-fcp S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Nov 23, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 23, 2025

r? @dswij

rustbot has assigned @dswij.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@github-actions
Copy link

github-actions bot commented Nov 23, 2025

No changes for e40774c

@ada4a
Copy link
Contributor

ada4a commented Nov 25, 2025

Looking at Lintcheck, at least the prost warnings seem to be FPs, let len: usize = iter.sum(); len as u64 is necessary, as iter is an Iterator<Item=usize>, and so can't be .sum()-ed up to a u64.

Judging by the comment in rustix, the warning seems to be a FP as well, because let fd: libc::c_int = fd; is effectively a cast, though I'm not fully sure about this one.

I don't really know how one would go on about recognizing such FPs, so maybe this lint would just need to be pedantic

@dswij
Copy link
Member

dswij commented Nov 27, 2025

r? clippy

@rustbot rustbot assigned llogiq and unassigned dswij Nov 27, 2025
Copy link
Contributor

@llogiq llogiq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could reduce the false positive by not linting if the initializer is a method call where the method has a placeholder result type.

Otherwise I'm afraid this lint will be too noisy to be useful, even as pedantic.

View changes since this review

let_expr: &rustc_hir::LetExpr<'a>,
bindings: &mut FxHashMap<HirId, BindingInfo<'a>>,
) {
if let_expr.ty.is_none() {
Copy link
Contributor

@llogiq llogiq Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lint should have a from_expansion check to avoid linting code in macros.

Yes, it's possible that there may be wins, but often macros have been written a certain way for a reason, and this might reduce the noise the lint makes.

Copy link
Author

@borngraced borngraced Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cd30783 added checks to skip:

  • macro-expanded bindings, usages, and casts
  • casts inside generic function/method calls
  • bindings initialized from functions with generic return types
  • generic constructors (e.g., Some(a as i32))

Also, track usages inside closures, handle nested blocks, expand test coverage.

Comment on lines 154 to 173
if usages.is_empty() {
return;
}

if !usages.iter().all(|u| u.is_cast) {
return;
}

let Some(first_target) = usages.first().and_then(|u| u.cast_to) else {
return;
};

if !usages.iter().all(|u| u.cast_to == Some(first_target)) {
return;
}

if first_target == binding_info.source_ty {
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of those checks could be one if-let chain.

#![allow(clippy::no_effect, clippy::unnecessary_cast, unused)]

fn main() {
// Should lint: let binding always cast to i32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those tests only cover local variables and a few binary ops. What about function and method calls? Especially if those functions might be generic, and doubly especially if they have a generic return type, like .sum().

@borngraced
Copy link
Author

borngraced commented Nov 28, 2025

I think we could reduce the false positive by not linting if the initializer is a method call where the method has a placeholder result type.

Otherwise I'm afraid this lint will be too noisy to be useful, even as pedantic.

View changes since this review

Yeah, I'd assume in a case like this:

  let a: u8 = some_iterator.next().unwrap();
  let _ = a as i32;

Here, next() returns Option<T> and unwrap() returns T. The T is inferred from the u8 type annotation. If we suggest changing to i32, the inference would break.

@llogiq
Copy link
Contributor

llogiq commented Dec 3, 2025

this still appears to be a false positive: The transmute has no type annotations, so the return type is inferred from the outside. Changing that would change behavior and potentially cause undefined behavior. So apparently your check for generic return types misses this function.

One thing we may want to do (in addition to fixing the generic return type check) is to omit the lint if there is any unsafe in the initializer.

@borngraced
Copy link
Author

this still appears to be a false positive: The transmute has no type annotations, so the return type is inferred from the outside. Changing that would change behavior and potentially cause undefined behavior. So apparently your check for generic return types misses this function.

One thing we may want to do (in addition to fixing the generic return type check) is to omit the lint if there is any unsafe in the initializer.

I guess since the actual issue is about generic return types being hidden inside blocks and not about unsafe itself, omitting the lint if there is any unsafe in the initializer can be too strict for unsafe blocks. Moreover, many unsafe operations have concrete types and are valid lint targets...what do you think @llogiq

@llogiq
Copy link
Contributor

llogiq commented Dec 3, 2025

In that case, at least the check for generics should peel blocks (even unsafe ones).

I still don't think that we should lint this in unsafe code at all. The risk of getting something wrong leading to catastrophic results just isn't worth the benefit of code simplification.

@rustbot
Copy link
Collaborator

rustbot commented Dec 4, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-fcp S-waiting-on-review Status: Awaiting review from the assignee but also interested parties

Projects

None yet

Development

Successfully merging this pull request may close these issues.

needless_type_cast suggests defining bindings as their cast type

5 participants