Skip to content

New lint : "const with a static lifetime" #1829

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

Closed
wants to merge 4 commits into from
Closed

New lint : "const with a static lifetime" #1829

wants to merge 4 commits into from

Conversation

gbip
Copy link
Contributor

@gbip gbip commented Jun 14, 2017

Hello,

This is the implementation for a new lint: it warns against 'static lifetimes when declaring constants, as discussed in #1762.
Since all the tests work with this implementation, I guess you can now merge it.
Please take a look at all English sentences, since English is not my native language it might be full of mistakes even if I was very careful.
Thanks !

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

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

Great initial impl.

#![feature(plugin)]
#![plugin(clippy)]

const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a test for a &[&'static str]?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Of course !
I'll also add tests for tuples, I forgot about them.

fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
// Match only constants...
if let ItemKind::Const(ref var_type, ref expr) = item.node {
// ... which are actually variables, not declaration such as #![feature(clippy)] ...
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't get this check... I don't think attributes create any constants...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I added it, it is because I was having warning on things such as https://github.com/Manishearth/rust-clippy/blob/master/tests/cc_seme.rs:l1 and l2. I was running cargo test from the root folder if that helps
I don't know if this was a side effect from my code, but when I inspected the AST there was nodes which where constants without being Lit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Very confusing... I have no clue how those are related. Can you show the exact compiler output you get without this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Of course, here is the result : https://pastebin.com/tzWKUcnV
Can you point me where some piece of code that implement a visitor ? I know about serde's visitor for serializing/deserializing structs, but I am not familiar with this concept...

Copy link
Contributor

Choose a reason for hiding this comment

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

O_o that is really weird. Try dumping the expression itself with debug formatting with println so we see what that thing is.

https://github.com/Manishearth/rust-clippy/blob/7535afc0fa9cec38f0fdd3a9deafb44fb3e5fcf1/clippy_lints/src/mut_mut.rs#L36 is an example invocation of a visitor. Look below that for the implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, this is rustc inserted. But I'm not sure why... I'll look around. You can try to call the in_macro function, maybe it returns true on the item span?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this problem is fixed, I'll let you dive into it 😉
I prefer to spend time trying to implement a visitor.
I am not sure where to start : your example uses stuff from the hir module, but this is an early lint pass, so I'm not sure what to do. I think I will implement a recursive visitor manually.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh... sorry about that, should have paid more attention. https://github.com/Manishearth/rust-clippy/blob/3b3e47f4518d83ab625d34e93f0855b713ebd1c3/clippy_lints/src/non_expressive_names.rs#L81 is a (convoluted) example of an AST visitor

Copy link
Contributor

Choose a reason for hiding this comment

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

I tested it. You just need to add

        if in_macro(item.span) {
            return;
        }

to the beginning of the check_item method

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will take care of finishing the implementation after Wednesday, I'm a little bit busy before... Thanks for the tip !

// ... which are actually variables, not declaration such as #![feature(clippy)] ...
if let ExprKind::Lit(_) = expr.node {
// ... which are reference ...
if let TyKind::Rptr(ref optionnal_lifetime, _) = var_type.node {
Copy link
Contributor

Choose a reason for hiding this comment

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

This only checks for &'static T, but not (&'static T, U). You need to use a visitor to find all 'static lifetimes that are contained in the type.

// ... and have an explicit 'static lifetime ...
if let Some(lifetime) = *optionnal_lifetime {
if lifetime.ident.name == "'static" {
span_help_and_lint(cx,
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use span_lint_and_then to add a suggestion to replace the lifetime with the empty string


declare_lint! {
pub CONST_STATIC_LIFETIME,
Warn,
Copy link
Member

Choose a reason for hiding this comment

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

I don't know if this should be Warn by default, at least not now. This warns against a syntax that was the only possible syntax for a long time, and lots of projects are using it now. Plus there is little value in updating old code except for "it's possible that way now".

Maybe we should ask for the lint level to be a dynamic parameter to rustc's devs. That way we could have a minimal_rustc_version parameter in clippy.toml, and only have the lint warn if the minimal version of rustc you want to support is higher that whatever version of rustc added that shortcut.

Copy link
Contributor

Choose a reason for hiding this comment

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

Well.. there was no need to update from try macro invocations to the question mark operator, other than readability. But yes, we should delay making it warn by default for the next few releases. I think 3 releases compatibility is what nursery crates require.

@@ -69,7 +69,7 @@ struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> {
// this list contains lists of names that are allowed to be similar
// the assumption is that no name is ever contained in multiple lists.
#[cfg_attr(rustfmt, rustfmt_skip)]
const WHITELIST: &'static [&'static [&'static str]] = &[
const WHITELIST: &[&[&str]] = &[
Copy link
Member

Choose a reason for hiding this comment

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

Wow that's better 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

C'mon, It's my first time implementing a lint, even touching something relating to compiler stuff, please be tolerant. Even if it is disabled by default I would be happy 😄

Copy link
Member

Choose a reason for hiding this comment

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

This was a positive comment… 😕

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I'm sorry, I thought it was sarcastic 😞

| ^^^^^^^
|
= note: `-D const-static-lifetime` implied by `-D warnings`
= help: consider removing the `'static`
Copy link
Member

Choose a reason for hiding this comment

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

You could try adding a suggestion for rustfix 😄

@gbip
Copy link
Contributor Author

gbip commented Jun 28, 2017

Since I am now in holiday, I currently have no motivation to try to finish this implementation. I will do it by the end of the summer !

@gbip
Copy link
Contributor Author

gbip commented Oct 18, 2017

I made a new fork (to start fresh since I was a few month late on upstream) and a new pull request at #2151.
I think this PR can be closed.

@oli-obk oli-obk closed this Oct 19, 2017
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.

3 participants