Skip to content

Add lint for debug_assert_with_mut_call - #4680

Merged
bors merged 1 commit into
rust-lang:masterfrom
hellow554:debug_assert_mut_call
Oct 23, 2019
Merged

Add lint for debug_assert_with_mut_call#4680
bors merged 1 commit into
rust-lang:masterfrom
hellow554:debug_assert_mut_call

Conversation

@hellow554

@hellow554 hellow554 commented Oct 16, 2019

Copy link
Copy Markdown
Contributor

closes #1526

What does not work:

  • detecting a mut call in the format string itself, e.g. debug_assert!(false, "{}", vec![1].pop())
  • detecting *mut T usage (pointer)

changelog: add new lint debug_assert_with_mut_call

Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs
Comment thread clippy_lints/src/mutable_debug_assertion.rs
Comment thread tests/ui/debug_assert_with_mut_call.stderr Outdated
@hellow554
hellow554 requested a review from flip1995 October 16, 2019 13:06
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs
Comment thread src/lintlist/mod.rs Outdated
Comment thread tests/ui/debug_assert_with_mut_call.rs
@hellow554
hellow554 requested a review from flip1995 October 16, 2019 17:43
Comment thread tests/ui/debug_assert_with_mut_call.rs
@bors

bors commented Oct 18, 2019

Copy link
Copy Markdown
Contributor

☔ The latest upstream changes (presumably #4657) made this pull request unmergeable. Please resolve the merge conflicts.

@hellow554

Copy link
Copy Markdown
Contributor Author

I think I'm done with this? @flip1995 do you want to see anything else? If not, I would rebase and force push the commits and pretty up the first comment in this thread. Are you okay with that?

@hellow554
hellow554 force-pushed the debug_assert_mut_call branch 2 times, most recently from 58f32c5 to 0dfeca0 Compare October 21, 2019 08:37
@hellow554

Copy link
Copy Markdown
Contributor Author

Rebased and ready to ship 🎉

@hellow554 hellow554 changed the title [WIP] Add first implementation for debug_assert macros with mutable parameters Add lint for debug_assert_with_mut_call Oct 21, 2019
@flip1995

Copy link
Copy Markdown
Member

I just got one more test idea:

let mut x = 42_usize;
debug_assert!({
    foo(&mut x);
    x > 10
});

@hellow554

hellow554 commented Oct 21, 2019

Copy link
Copy Markdown
Contributor Author
let mut x = 42_usize;
debug_assert!({
    foo(&mut x);
    x > 10
});

That's nasty! Who writes such code ^^
Ofc it isn't covered yet. Adding code for it :/

Btw: every block isn't covered yet, e.g. if, match, for, while. Do you think adding them is worth it? (I don't think so)

@hellow554

hellow554 commented Oct 21, 2019

Copy link
Copy Markdown
Contributor Author
error: do not call functions with mutable arguments inside of a `debug_assert!`
   --> tests/ui/debug_assert_with_mut_call.rs:104:19
    |
104 |       debug_assert!({
    |  ___________________^
105 | |         bool_mut(&mut x);
106 | |         x > 10
107 | |     });
    | |_____^

the span now doesn't point at the function call, but to the block itself. Meh :/

On the other hand:

error: do not call functions with mutable arguments inside of a `debug_assert!`
   --> tests/ui/debug_assert_with_mut_call.rs:105:9
    |
105 |         bool_mut(&mut x);
    |         ^^^^^^^^^^^^^^^^
    |

This doesn't look like if it's inside the debug_assert macro at all. What do you think about this @flip1995

@hellow554

Copy link
Copy Markdown
Contributor Author

I've gone full retard mode now and covered every ExprKind. I think this coveres everything, except closures and inline assembly (No... just, no) ^^

@hellow554
hellow554 force-pushed the debug_assert_mut_call branch from 7e638e1 to c1d2ed1 Compare October 21, 2019 13:30
@flip1995

Copy link
Copy Markdown
Member

That's nasty! Who writes such code

This makes sense, when you want to write more complex verification code. Though the simplest example is asserting an enum variant:

debug_assert!(if let Variant(_) = expr {
    true
} else {
    false
});

I've gone full retard mode now and covered every ExprKind.

Uh, now you basically rewritten a Visitor. It may be better to just implement this, then you just have to do:

struct MutArgVisitor {
    mut_arg_found: bool,
}

impl intravisit::Visitor for MutArgVisitor {
    fn visit_expr(&mut self, expr: &'_ Expr) {
        match &expr.kind {
            ExprKind::Call(.., args) | ExprKind::MethodCall(.., args) => {
                // check args, 
                if /* any arg is mutable */ {
                     self.mut_arg_found = true;
                }
            }
        }

        walk_expr(expr);
    }
}

Just grep the Clippy Codebase for intravisit to find more examples on how to write and use Visitors.

@hellow554

Copy link
Copy Markdown
Contributor Author

@Manishearth can you help me again please? I try to solve the *mut pointer issue, but I can't get the type from adjustments table:

[clippy_lints/src/mutable_debug_assertion.rs:131] &expr.kind = Call(
    expr(HirId { owner: DefIndex(36), local_id: 1089 }: bool_ptr_mut),
    [
        expr(HirId { owner: DefIndex(36), local_id: 1091 }: v),
    ],
)
[clippy_lints/src/mutable_debug_assertion.rs:131] &expr.kind = Path(
    Resolved(
        None,
        path(bool_ptr_mut),
    ),
)
[clippy_lints/src/mutable_debug_assertion.rs:138] self.cx.tables.adjustments().get(expr.hir_id) = None
[clippy_lints/src/mutable_debug_assertion.rs:131] &expr.kind = Path(
    Resolved(
        None,
        path(v),
    ),
)
[clippy_lints/src/mutable_debug_assertion.rs:138] self.cx.tables.adjustments().get(expr.hir_id) = None

This is the debug output of bool_ptr_mut(v) where v is a *mut u32 with fn bool_ptr_mut(_: *mut u32) -> bool { false }.
As you can see the adjustements table doesn't have the type of v in it's Vec. What am I missing here?

@Manishearth

Copy link
Copy Markdown
Member

tbh I feel like it's fine if we don't detect that case. The lint is already quite advanced (and I'm hoping it's not too slow to apply)

Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated

@flip1995 flip1995 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The usage of the visitor should be more like the one of other visitors in the code base. Also as @Manishearth wrote, you can just leave out the mut pointer case.

Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
Comment thread clippy_lints/src/mutable_debug_assertion.rs Outdated
@hellow554

Copy link
Copy Markdown
Contributor Author

If you give the okay fir this PR, I will rebase it again and then it can be merged (finally) 🎉

@flip1995 flip1995 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks great now, thanks! Rebase and this is ready to go

This lint will complain when you put a mutable function/method call
inside a `debug_assert` macro, because it will not be executed in
release mode, therefore it will change the execution flow, which is not
wanted.
@hellow554
hellow554 force-pushed the debug_assert_mut_call branch from 1d15a9c to 5572476 Compare October 22, 2019 08:40
@hellow554

Copy link
Copy Markdown
Contributor Author

Done. Waiting for travis (which failed the last two times, is there something broken?)

@flip1995

Copy link
Copy Markdown
Member

Unrelated to this PR. Rustup in #4715

@phansch

phansch commented Oct 23, 2019

Copy link
Copy Markdown
Contributor

@bors r=flip1995

@bors

bors commented Oct 23, 2019

Copy link
Copy Markdown
Contributor

📌 Commit 5572476 has been approved by flip1995

@bors

bors commented Oct 23, 2019

Copy link
Copy Markdown
Contributor

⌛ Testing commit 5572476 with merge 850dfda...

bors added a commit that referenced this pull request Oct 23, 2019
Add lint for debug_assert_with_mut_call

closes #1526

**What does not work:**

* detecting a mut call in the format string itself, e.g. `debug_assert!(false, "{}", vec![1].pop())`
* detecting `*mut T` usage (pointer)

---

changelog: add new lint `debug_assert_with_mut_call`
@bors

bors commented Oct 23, 2019

Copy link
Copy Markdown
Contributor

☀️ Test successful - checks-travis, status-appveyor
Approved by: flip1995
Pushing 850dfda to master...

@bors
bors merged commit 5572476 into rust-lang:master Oct 23, 2019
@hellow554
hellow554 deleted the debug_assert_mut_call branch January 16, 2020 10:42
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.

Detecting mutation in debug_assert!

6 participants