From 7ee4a9a659336b98a5cc76c172cbd0ffcfb3ed88 Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 16 Aug 2016 14:29:21 +0200
Subject: [PATCH 1/2] lint modules that have the same name as their parent
 module

---
 CHANGELOG.md                           |  1 +
 README.md                              |  3 +-
 clippy_lints/src/lib.rs                |  3 ++
 clippy_lints/src/module_inception.rs   | 47 ++++++++++++++++++++++++++
 tests/compile-fail/module_inception.rs | 16 +++++++++
 5 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 clippy_lints/src/module_inception.rs
 create mode 100644 tests/compile-fail/module_inception.rs

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffb5ad82f1b..725cdcc10b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -222,6 +222,7 @@ All notable changes to this project will be documented in this file.
 [`min_max`]: https://github.com/Manishearth/rust-clippy/wiki#min_max
 [`misrefactored_assign_op`]: https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op
 [`mixed_case_hex_literals`]: https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals
+[`module_inception`]: https://github.com/Manishearth/rust-clippy/wiki#module_inception
 [`modulo_one`]: https://github.com/Manishearth/rust-clippy/wiki#modulo_one
 [`mut_mut`]: https://github.com/Manishearth/rust-clippy/wiki#mut_mut
 [`mutex_atomic`]: https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic
diff --git a/README.md b/README.md
index 4e6f864fec3..1da19a71044 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Table of contents:
 
 ## Lints
 
-There are 163 lints included in this crate:
+There are 164 lints included in this crate:
 
 name                                                                                                                 | default | triggers on
 ---------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
@@ -100,6 +100,7 @@ name
 [min_max](https://github.com/Manishearth/rust-clippy/wiki#min_max)                                                   | warn    | `min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant
 [misrefactored_assign_op](https://github.com/Manishearth/rust-clippy/wiki#misrefactored_assign_op)                   | warn    | having a variable on both sides of an assign op
 [mixed_case_hex_literals](https://github.com/Manishearth/rust-clippy/wiki#mixed_case_hex_literals)                   | warn    | hex literals whose letter digits are not consistently upper- or lowercased
+[module_inception](https://github.com/Manishearth/rust-clippy/wiki#module_inception)                                 | warn    | modules that have the same name as their parent module
 [modulo_one](https://github.com/Manishearth/rust-clippy/wiki#modulo_one)                                             | warn    | taking a number modulo 1, which always returns 0
 [mut_mut](https://github.com/Manishearth/rust-clippy/wiki#mut_mut)                                                   | allow   | usage of double-mut refs, e.g. `&mut &mut ...`
 [mutex_atomic](https://github.com/Manishearth/rust-clippy/wiki#mutex_atomic)                                         | warn    | using a mutex where an atomic value could be used instead
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 260b5c1ba57..3a5051b9308 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -96,6 +96,7 @@ pub mod methods;
 pub mod minmax;
 pub mod misc;
 pub mod misc_early;
+pub mod module_inception;
 pub mod mut_mut;
 pub mod mut_reference;
 pub mod mutex_atomic;
@@ -173,6 +174,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
     reg.register_early_lint_pass(box utils::internal_lints::Clippy);
     reg.register_late_lint_pass(box types::TypePass);
     reg.register_late_lint_pass(box booleans::NonminimalBool);
+    reg.register_early_lint_pass(box module_inception::Pass);
     reg.register_late_lint_pass(box misc::TopLevelRefPass);
     reg.register_late_lint_pass(box misc::CmpNan);
     reg.register_late_lint_pass(box eq_op::EqOp);
@@ -384,6 +386,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
         misc_early::MIXED_CASE_HEX_LITERALS,
         misc_early::REDUNDANT_CLOSURE_CALL,
         misc_early::UNNEEDED_FIELD_PATTERN,
+        module_inception::MODULE_INCEPTION,
         mut_reference::UNNECESSARY_MUT_PASSED,
         mutex_atomic::MUTEX_ATOMIC,
         needless_bool::BOOL_COMPARISON,
diff --git a/clippy_lints/src/module_inception.rs b/clippy_lints/src/module_inception.rs
new file mode 100644
index 00000000000..8215929291c
--- /dev/null
+++ b/clippy_lints/src/module_inception.rs
@@ -0,0 +1,47 @@
+use rustc::lint::*;
+use syntax::ast::*;
+use utils::span_lint;
+
+/// **What it does:** Checks for modules that have the same name as their parent module
+///
+/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. }` in `foo.rs`
+///
+/// **Known problems:** None.
+///
+/// **Example:**
+/// ```rust
+/// // lib.rs
+/// mod foo;
+/// // foo.rs
+/// mod foo {
+///     ...
+/// }
+/// ```
+declare_lint! {
+    pub MODULE_INCEPTION,
+    Warn,
+    "modules that have the same name as their parent module"
+}
+
+pub struct Pass;
+
+impl LintPass for Pass {
+    fn get_lints(&self) -> LintArray {
+        lint_array![MODULE_INCEPTION]
+    }
+}
+
+impl EarlyLintPass for Pass {
+    fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
+        if let ItemKind::Mod(ref module) = item.node {
+            for sub_item in &module.items {
+                if let ItemKind::Mod(_) = sub_item.node {
+                    if item.ident == sub_item.ident {
+                        span_lint(cx, MODULE_INCEPTION, sub_item.span,
+                                  "module has the same name as its containing module");
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/compile-fail/module_inception.rs b/tests/compile-fail/module_inception.rs
new file mode 100644
index 00000000000..499daadee69
--- /dev/null
+++ b/tests/compile-fail/module_inception.rs
@@ -0,0 +1,16 @@
+#![feature(plugin)]
+#![plugin(clippy)]
+#![deny(module_inception)]
+
+mod foo {
+    mod bar {
+        mod bar { //~ ERROR module has the same name as its containing module
+
+        }
+    }
+    mod foo { //~ ERROR module has the same name as its containing module
+
+    }
+}
+
+fn main() {}

From b6f320a495d2d144b22c5a5fcfda1488e3d5133b Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 16 Aug 2016 14:36:48 +0200
Subject: [PATCH 2/2] address nits and improve docs

---
 clippy_lints/src/module_inception.rs   | 5 ++++-
 tests/compile-fail/module_inception.rs | 5 +++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/module_inception.rs b/clippy_lints/src/module_inception.rs
index 8215929291c..10c8154d100 100644
--- a/clippy_lints/src/module_inception.rs
+++ b/clippy_lints/src/module_inception.rs
@@ -4,7 +4,10 @@ use utils::span_lint;
 
 /// **What it does:** Checks for modules that have the same name as their parent module
 ///
-/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. }` in `foo.rs`
+/// **Why is this bad?** A typical beginner mistake is to have `mod foo;` and again `mod foo { .. }` in `foo.rs`.
+///                      The expectation is that items inside the inner `mod foo { .. }` are then available
+///                      through `foo::x`, but they are only available through `foo::foo::x`.
+///                      If this is done on purpose, it would be better to choose a more representative module name.
 ///
 /// **Known problems:** None.
 ///
diff --git a/tests/compile-fail/module_inception.rs b/tests/compile-fail/module_inception.rs
index 499daadee69..88497c9a6a7 100644
--- a/tests/compile-fail/module_inception.rs
+++ b/tests/compile-fail/module_inception.rs
@@ -5,11 +5,12 @@
 mod foo {
     mod bar {
         mod bar { //~ ERROR module has the same name as its containing module
-
+            mod foo {}
         }
+        mod foo {}
     }
     mod foo { //~ ERROR module has the same name as its containing module
-
+        mod bar {}
     }
 }