Add manual_as_slice lint - #14809
Add manual_as_slice lint#14809nils-degroot wants to merge 1 commit into
manual_as_slice lint#14809Conversation
llogiq
left a comment
There was a problem hiding this comment.
This looks like a good starting point. I'd want some more test cases, and there is some duplication we can remove, but otherwise this seems mostly merge-worthy. I'd like to rename the lint though, it's too wordy. How about manual_as_slice? That fits very well into our naming structure. Also please squash your commits when ready.
|
I like |
1a8a066 to
dc4e07b
Compare
|
I think you need to re-bless the tests. |
as_slice_instead_of_reference_full_range lintmanual_as_slice lint
samueltardieu
left a comment
There was a problem hiding this comment.
You should at least check that:
- the resulting type is a slice
- the
.as_slice()/.as_mut_slice()methods exist on the original type
or restrict the original type to those coming from core/alloc.
Otherwise, you take the risk of having a type implement [..] for something else (let's say, in a domain-specific-language) without having .as_slice() available. Here is an example:
#![feature(new_range_api)]
use std::ops::Index;
use std::range::RangeBounds;
struct Count;
impl<R: RangeBounds<()>> Index<R> for Count {
type Output = ();
fn index(&self, _: R) -> &Self::Output {
&()
}
}
fn main() {
_ = &Count[..];
}It will suggest to use Count.as_slice() even though this method does not exist on Count.
|
I'm gonna restrict is to Vec, array and slice in that case, since doing this on a string also would not work |
|
Is it possible to get this working on vec since its not a language item? |
Language items are items that the compiler needs when it transforms code. For example, it needs However, |
llogiq
left a comment
There was a problem hiding this comment.
I'd like the message to be shorter. Otherwise this looks mostly good. We may want to select a different lint group though. I'll start the final comment period soon.
545c550 to
a8a448d
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
6f02288 to
750f2da
Compare
I think it would work, you'd just need to suggest |
|
Ping @nils-degroot are you willing to continue working on this? r? Jarcho |
|
Hey, forgot this was open. I'll handle the comments and rebase now |
750f2da to
dabee41
Compare
|
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. |
|
Lintcheck changes for dabee41
This comment will be updated if you push new changes |
| /// | ||
| /// ### Why is this bad? | ||
| /// | ||
| /// Using the `some_value.as_slice()` method is more explicit then using `&some_value[..]` |
There was a problem hiding this comment.
| /// Using the `some_value.as_slice()` method is more explicit then using `&some_value[..]` | |
| /// Using the `some_value.as_slice()` method is more explicit than using `&some_value[..]` |
| /// let array: [u8; 4] = [0; 4]; | ||
| /// let slice = array.as_slice(); | ||
| /// ``` | ||
| #[clippy::version = "1.88.0"] |
There was a problem hiding this comment.
| #[clippy::version = "1.88.0"] | |
| #[clippy::version = "1.100.0"] |
| /// ``` | ||
| #[clippy::version = "1.88.0"] | ||
| pub MANUAL_AS_SLICE, | ||
| nursery, |
There was a problem hiding this comment.
| nursery, | |
| pedantic, |
| if expr.span.from_expansion() { | ||
| return; | ||
| } | ||
|
|
||
| if let ExprKind::AddrOf(_, mutability, borrow) = expr.kind |
There was a problem hiding this comment.
nit: could extend the let-chain to make the code more concise
| if expr.span.from_expansion() { | |
| return; | |
| } | |
| if let ExprKind::AddrOf(_, mutability, borrow) = expr.kind | |
| if !expr.span.from_expansion() | |
| && let ExprKind::AddrOf(_, mutability, borrow) = expr.kind |
| }; | ||
|
|
||
| diag.multipart_suggestion( | ||
| "try", |
There was a problem hiding this comment.
let's make this a bit more descriptive
| "try", | |
| format!("use `{sugg_tail}` instead"), |
| { | ||
| match cx.typeck_results().expr_ty(value).kind() { | ||
| ty::Array(_, _) | ty::Slice(_) => {}, | ||
| ty::Ref(_, t, _) if let ty::Array(_, _) | ty::Slice(_) = t.kind() => {}, | ||
| ty::Adt(adt, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt.did()) => {}, | ||
| _ => return, | ||
| } |
There was a problem hiding this comment.
I think you could simplify this down to
| { | |
| match cx.typeck_results().expr_ty(value).kind() { | |
| ty::Array(_, _) | ty::Slice(_) => {}, | |
| ty::Ref(_, t, _) if let ty::Array(_, _) | ty::Slice(_) = t.kind() => {}, | |
| ty::Adt(adt, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt.did()) => {}, | |
| _ => return, | |
| } | |
| && !is_slice_like(cx.typeck_results().expr_ty_adjusted(value)) | |
| { |
| ty::Adt(adt, _) if cx.tcx.is_diagnostic_item(sym::Vec, adt.did()) => {}, | ||
| _ => return, | ||
| } | ||
|
|
There was a problem hiding this comment.
lintcheck shows that this lint currently fires on &[][..], for which [].as_slice() sounds overkill imo... consider not linting in that case?
|
This lint has been nominated for inclusion. |
|
Reminder, once the PR becomes ready for a review, use |
View all comments
This pr adds the
manual_as_slicelint.closes: #7633
changelog: add [
manual_as_slice] lint