]> git.lizzy.rs Git - rust.git/commitdiff
Move expression check to LateLintPass
authorVincent Dal Maso <vincent.dalmaso.ext@delair-tech.com>
Mon, 17 Jun 2019 15:36:42 +0000 (17:36 +0200)
committerflip1995 <hello@philkrones.com>
Mon, 5 Aug 2019 11:23:30 +0000 (13:23 +0200)
Changes:
- Move from EarlyLintPass
- Fix entrypoint check with function path def_id.

CHANGELOG.md
clippy_lints/src/lib.rs
clippy_lints/src/main_recursion.rs
src/lintlist/mod.rs
tests/ui/crate_level_checks/entrypoint_recursion.rs [new file with mode: 0644]
tests/ui/crate_level_checks/entrypoint_recursion.stderr [new file with mode: 0644]
tests/ui/crate_level_checks/no_std_main_recursion.rs
tests/ui/crate_level_checks/no_std_main_recursion.stderr [deleted file]
tests/ui/crate_level_checks/std_main_recursion.rs
tests/ui/crate_level_checks/std_main_recursion.stderr

index 089897811a595aa128d57a3947ee68a8e7cc04ea..e4a1a602c4393292907cd474d050403094e0b351 100644 (file)
@@ -1000,6 +1000,7 @@ Released 2018-09-13
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
+[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
 [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
index 325195caa3ec18cecfe62d7b1b84a4684dba4e0e..258be38e48b16c79f80206359466bd304e6e695b 100644 (file)
@@ -474,7 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
     reg.register_late_lint_pass(box types::LetUnitValue);
     reg.register_late_lint_pass(box types::UnitCmp);
     reg.register_late_lint_pass(box loops::Loops);
-    reg.register_early_lint_pass(box main_recursion::MainRecursion::new());
+    reg.register_late_lint_pass(box main_recursion::MainRecursion::default());
     reg.register_late_lint_pass(box lifetimes::Lifetimes);
     reg.register_late_lint_pass(box entry::HashMapPass);
     reg.register_late_lint_pass(box ranges::Ranges);
@@ -762,6 +762,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         loops::WHILE_IMMUTABLE_CONDITION,
         loops::WHILE_LET_LOOP,
         loops::WHILE_LET_ON_ITERATOR,
+        main_recursion::MAIN_RECURSION,
         map_clone::MAP_CLONE,
         map_unit_fn::OPTION_MAP_UNIT_FN,
         map_unit_fn::RESULT_MAP_UNIT_FN,
@@ -935,6 +936,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         loops::FOR_KV_MAP,
         loops::NEEDLESS_RANGE_LOOP,
         loops::WHILE_LET_ON_ITERATOR,
+        main_recursion::MAIN_RECURSION,
         map_clone::MAP_CLONE,
         matches::MATCH_BOOL,
         matches::MATCH_OVERLAPPING_ARM,
index 9ef4de21f5a9721cbaf206850c43ba5a7083a9e1..88f1e685ced3b3e4726f09d2efc9a68cc73effe3 100644 (file)
@@ -1,53 +1,60 @@
-
-use syntax::ast::{Crate, Expr, ExprKind};
-use syntax::symbol::sym;
-use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
+use rustc::hir::{Crate, Expr, ExprKind, QPath};
+use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
 use rustc::{declare_tool_lint, impl_lint_pass};
+use syntax::symbol::sym;
 
+use crate::utils::{is_entrypoint_fn, snippet, span_help_and_lint};
 use if_chain::if_chain;
-use crate::utils::span_help_and_lint;
 
 declare_clippy_lint! {
+    /// **What it does:** Checks for recursion using the entrypoint.
+    ///
+    /// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
+    /// recursing into main() seems like an unintuitive antipattern we should be able to detect.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```no_run
+    /// fn main() {
+    ///     main();
+    /// }
+    /// ```
     pub MAIN_RECURSION,
-    pedantic,
-    "function named `foo`, which is not a descriptive name"
+    style,
+    "recursion using the entrypoint"
 }
 
+#[derive(Default)]
 pub struct MainRecursion {
-    has_no_std_attr: bool
+    has_no_std_attr: bool,
 }
 
 impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
 
-impl MainRecursion {
-    pub fn new() -> MainRecursion {
-        MainRecursion {
-            has_no_std_attr: false
-        }
-    }
-}
-
-impl EarlyLintPass for MainRecursion {
-    fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
+impl LateLintPass<'_, '_> for MainRecursion {
+    fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate) {
         self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std);
     }
 
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
+    fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
         if self.has_no_std_attr {
             return;
         }
 
         if_chain! {
             if let ExprKind::Call(func, _) = &expr.node;
-            if let ExprKind::Path(_, path) = &func.node;
-            if *path == sym::main;
+            if let ExprKind::Path(path) = &func.node;
+            if let QPath::Resolved(_, path) = &path;
+            if let Some(def_id) = path.res.opt_def_id();
+            if is_entrypoint_fn(cx, def_id);
             then {
                 span_help_and_lint(
                     cx,
                     MAIN_RECURSION,
-                    expr.span,
-                    "You are recursing into main()",
-                    "Consider using another function for this recursion"
+                    func.span,
+                    &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
+                    "consider using another function for this recursion"
                 )
             }
         }
index aa457664020975c7bd237c715d83db01f2b029d0..802ba60b9f1c7360393d7f411911649e60f66e74 100644 (file)
         deprecation: None,
         module: "booleans",
     },
+    Lint {
+        name: "main_recursion",
+        group: "style",
+        desc: "recursion using the entrypoint",
+        deprecation: None,
+        module: "main_recursion",
+    },
     Lint {
         name: "manual_memcpy",
         group: "perf",
diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs
new file mode 100644 (file)
index 0000000..995787c
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-macos
+// ignore-windows
+
+#![feature(main)]
+
+#[warn(clippy::main_recursion)]
+#[allow(unconditional_recursion)]
+#[main]
+fn a() {
+    println!("Hello, World!");
+    a();
+}
diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr
new file mode 100644 (file)
index 0000000..f52fc94
--- /dev/null
@@ -0,0 +1,11 @@
+error: recursing into entrypoint `a`
+  --> $DIR/entrypoint_recursion.rs:11:5
+   |
+LL |     a();
+   |     ^
+   |
+   = note: `-D clippy::main-recursion` implied by `-D warnings`
+   = help: consider using another function for this recursion
+
+error: aborting due to previous error
+
index 857af96a0443f6627aeea1c95699c57a075064d0..4d19f38e2d0a1b6ee829cee4361bb7aea94acbd7 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(lang_items, link_args, start, libc)]
-#![link_args="-nostartfiles"]
+#![link_args = "-nostartfiles"]
 #![no_std]
 
 use core::panic::PanicInfo;
@@ -8,7 +8,6 @@
 static N: AtomicUsize = AtomicUsize::new(0);
 
 #[warn(clippy::main_recursion)]
-#[allow(unconditional_recursion)]
 #[start]
 fn main(argc: isize, argv: *const *const u8) -> isize {
     let x = N.load(Ordering::Relaxed);
@@ -28,4 +27,4 @@ fn panic(_info: &PanicInfo) -> ! {
 }
 
 #[lang = "eh_personality"]
-extern fn eh_personality() {}
+extern "C" fn eh_personality() {}
diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.stderr b/tests/ui/crate_level_checks/no_std_main_recursion.stderr
deleted file mode 100644 (file)
index e69de29..0000000
index e7689ffb72d379940012f8bf70a84cae94ad3c22..89ff6609934d2cac98f83f5a4d4ddc6e91b1e6c0 100644 (file)
@@ -1,5 +1,6 @@
 #[warn(clippy::main_recursion)]
 #[allow(unconditional_recursion)]
 fn main() {
+    println!("Hello, World!");
     main();
 }
index 7979010eadf004547ef0a3d88b011b960c587eae..0a260f9d2309ea9a5cf39e9003a8f580d235f8bb 100644 (file)
@@ -1,11 +1,11 @@
-error: You are recursing into main()
-  --> $DIR/std_main_recursion.rs:4:5
+error: recursing into entrypoint `main`
+  --> $DIR/std_main_recursion.rs:5:5
    |
 LL |     main();
-   |     ^^^^^^
+   |     ^^^^
    |
    = note: `-D clippy::main-recursion` implied by `-D warnings`
-   = help: Consider using another function for this recursion
+   = help: consider using another function for this recursion
 
 error: aborting due to previous error