Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lint against String.repeat(1) #3060

Closed
wants to merge 1 commit into from

Conversation

einashaddad
Copy link

No description provided.


/// **What it does:** Checks for usage of `.repeat(1)` since its equivalent to clone()
///
/// **Why is this bad?** It's more readable.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd say it's the opposite.

declare_clippy_lint! {
pub STRING_REPEAT_ONCE,
pedantic,
" using `String.repeat(1)` instead of `String.clone()`"
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove white space preceding using.

Copy link
Member

@flip1995 flip1995 left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution and welcome to Clippy! I commented on mostly small things that you could improve.

let a = "this shouldn't work".repeat(1);
let b = String::from("neither should this");
let c = b.repeat(1);
let d = "this works".repeat(2);
Copy link
Member

Choose a reason for hiding this comment

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

What happens if you use a constant as the argument of repeat:

const N: u32 = 1;
b.repeat(N);

use syntax::ast::LitKind;
use crate::utils::{in_macro, snippet};

if let ExprKind::MethodCall(ref path, _, ref args) = e.node {
Copy link
Member

Choose a reason for hiding this comment

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

NIT: you can use the if_chain!() macro here to avoid the nested if syntax

/// **What it does:** Checks for usage of `.repeat(1)` since its equivalent to clone()
///
/// **Why is this bad?** `.repeat(1)` is not very readable.
///
Copy link
Member

Choose a reason for hiding this comment

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

**Known problems:** None.

@@ -169,3 +169,61 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
}
}
}

/// **What it does:** Checks for usage of `.repeat(1)` since its equivalent to clone()
Copy link
Member

Choose a reason for hiding this comment

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

Missing backticks around .clone()

Maybe add something like "while clone represents the intention better."

Copy link
Member

Choose a reason for hiding this comment

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

Please also include #3060 (comment) in the lint documentation.


/// **What it does:** Checks for usage of `.repeat(1)` since its equivalent to clone()
///
/// **Why is this bad?** `.repeat(1)` is not very readable.
Copy link
Member

Choose a reason for hiding this comment

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

Here it might also be better to talk about the hidden intention behind the repeat(1) call.

"Isn't very readable" is a very vague argument for a lint.

@@ -303,6 +303,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
reg.register_late_lint_pass(box block_in_if_condition::BlockInIfCondition);
reg.register_late_lint_pass(box unicode::Unicode);
reg.register_late_lint_pass(box strings::StringAdd);
reg.register_late_lint_pass(box strings::StringRepeatOnce);
Copy link
Member

Choose a reason for hiding this comment

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

You also have to add the Lint to the right point group. Running the util/update_lints.py script should do this for you!

/// ```
declare_clippy_lint! {
pub STRING_REPEAT_ONCE,
pedantic,
Copy link
Member

Choose a reason for hiding this comment

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

I would classify this as a complexity lint. If too many people complain about this lint (which I don't think) we can move this to pedantic later.

@matthiaskrgr
Copy link
Member

Should we perhaps limit this to a few known std types that implement repeat()?

When I make my own type and impl repeat(), we can't really know that repeat(1) isn't totally legit in this case and maybe don't want to warn. Thoughts?

struct Hello {
	x: i32,
}

impl Hello {
	fn repeat(&mut self, number: i32) {
		self.x +=number * 3;
	}
}

fn main() {
    let mut a = Hello { x: 7 }; 
    a.repeat(1);
    println!("a: {}", a.x);
}

If I tested this correctly I also got a warning for this case.

@flip1995
Copy link
Member

@matthiaskrgr Yes good point! Searching in the doc of the std library there are 3 types where it makes sense:

  1. str: here repeat(1) creates a String. The suggestion should be to use .to_string() instead. This would be a case of new lint for &str to String conversion #2824
  2. String: we can suggest .clone() here
  3. slice: we can suggest to_vec() here. (This is feature gated, but easy to implement, if the other two cases are covered)

This should cover all the cases: Playground

Did I miss something?

@einashaddad You practically just have to add a match over the type of args[0] and adapt the suggestion. For the type String there is already a method is_string you can use:
https://github.com/rust-lang-nursery/rust-clippy/blob/f05a1038b59cd4217e58b3aef7a0751a0efd01e4/clippy_lints/src/strings.rs#L120-L122

@einashaddad
Copy link
Author

Thanks for the review @flip1995, @matthiaskrgr & @mati865. Sounds good, I'll address.

@flip1995 flip1995 added the S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) label Sep 3, 2018
@flip1995
Copy link
Member

flip1995 commented Sep 6, 2018

ping @einashaddad
Are you still working on this? Do you have any questions we can help you with?

@flip1995
Copy link
Member

Ping from triage @einashaddad. Do you want to continue working on this?

@flip1995
Copy link
Member

Ping from triage @einashaddad: It looks like this PR hasn't received any updates in a while, so I'm closing it per our new guidelines. Thank you for your contributions and please feel free to re-open in the future.

@flip1995 flip1995 closed this Dec 27, 2018
@flip1995 flip1995 added S-inactive-closed Status: Closed due to inactivity and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Dec 27, 2018
@HKalbasi
Copy link
Member

finished in #5773
@rustbot label -S-inactive-closed

@HKalbasi
Copy link
Member

@rustbot label -S-inactive-closed

@flip1995 flip1995 removed the S-inactive-closed Status: Closed due to inactivity label Jul 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants