From 4dded23925994103e3e793d5edbe0d30222cdaa4 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Mon, 28 Feb 2022 19:59:21 -0500 Subject: [PATCH 1/4] add `special_module_name` lint --- compiler/rustc_lint/src/builtin.rs | 74 +++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 1 + src/test/ui/modules/dummy.rs | 0 src/test/ui/modules/special_module_name.rs | 8 ++ .../ui/modules/special_module_name.stderr | 37 ++++++++++ .../ui/modules/special_module_name_ignore.rs | 9 +++ 6 files changed, 129 insertions(+) create mode 100644 src/test/ui/modules/dummy.rs create mode 100644 src/test/ui/modules/special_module_name.rs create mode 100644 src/test/ui/modules/special_module_name.stderr create mode 100644 src/test/ui/modules/special_module_name_ignore.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 30b5f9b34d099..961e1e9507b97 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3248,3 +3248,77 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } } } + +declare_lint! { + /// The `special_module_name` lint detects module + /// declarations for files that have a special meaning. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// mod lib; + /// + /// fn main() { + /// lib::run(); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Cargo recognizes `lib.rs` and `main.rs` as the root of a + /// library or binary crate, so declaring them as modules + /// will lead to miscompilation of the crate unless configured + /// explicitly. + /// + /// To access a library from a binary target within the same crate, + /// use `your_crate_name::` as the path path instead of `lib::`: + /// + /// ```rust,compile_fail + /// // bar/src/lib.rs + /// fn run() { + /// // ... + /// } + /// + /// // bar/src/main.rs + /// fn main() { + /// bar::run(); + /// } + /// ``` + /// + /// Binary targets cannot be used as libraries and so declaring + /// one as a module is not allowed. + pub SPECIAL_MODULE_NAME, + Warn, + "module declarations for files with a special meaning", +} + +declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]); + +impl EarlyLintPass for SpecialModuleName { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { + for item in &krate.items { + if let ast::ItemKind::Mod(..) = item.kind { + if item.attrs.iter().any(|a| a.has_name(sym::path)) { + continue; + } + + match item.ident.name.as_str() { + "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| { + lint.build("found module declaration for lib.rs") + .note("lib.rs is the root of this crate's library target") + .help("to refer to it from other targets, use the library's name as the path") + .emit() + }), + "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| { + lint.build("found module declaration for main.rs") + .note("a binary crate cannot be used as library") + .emit() + }), + _ => continue + } + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 69863b5ff827f..107df79c3809b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -129,6 +129,7 @@ macro_rules! early_lint_passes { UnusedBraces: UnusedBraces, UnusedImportBraces: UnusedImportBraces, UnsafeCode: UnsafeCode, + SpecialModuleName: SpecialModuleName, AnonymousParameters: AnonymousParameters, EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), NonCamelCaseTypes: NonCamelCaseTypes, diff --git a/src/test/ui/modules/dummy.rs b/src/test/ui/modules/dummy.rs new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/test/ui/modules/special_module_name.rs b/src/test/ui/modules/special_module_name.rs new file mode 100644 index 0000000000000..15c59b2da828c --- /dev/null +++ b/src/test/ui/modules/special_module_name.rs @@ -0,0 +1,8 @@ +mod lib; +//~^ WARN found module declaration for lib.rs +//~| ERROR file not found for module `lib` +mod main; +//~^ WARN found module declaration for main.rs +//~| ERROR file not found for module `main` + +fn main() {} diff --git a/src/test/ui/modules/special_module_name.stderr b/src/test/ui/modules/special_module_name.stderr new file mode 100644 index 0000000000000..8b3da29386df2 --- /dev/null +++ b/src/test/ui/modules/special_module_name.stderr @@ -0,0 +1,37 @@ +error[E0583]: file not found for module `lib` + --> $DIR/special_module_name.rs:1:1 + | +LL | mod lib; + | ^^^^^^^^ + | + = help: to create the module `lib`, create file "$DIR/lib.rs" or "$DIR/lib/mod.rs" + +error[E0583]: file not found for module `main` + --> $DIR/special_module_name.rs:4:1 + | +LL | mod main; + | ^^^^^^^^^ + | + = help: to create the module `main`, create file "$DIR/main.rs" or "$DIR/main/mod.rs" + +warning: found module declaration for lib.rs + --> $DIR/special_module_name.rs:1:1 + | +LL | mod lib; + | ^^^^^^^^ + | + = note: `#[warn(special_module_name)]` on by default + = note: lib.rs is the root of this crate's library target + = help: to refer to it from other targets, use the library's name as the path + +warning: found module declaration for main.rs + --> $DIR/special_module_name.rs:4:1 + | +LL | mod main; + | ^^^^^^^^^ + | + = note: a binary crate cannot be used as library + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/modules/special_module_name_ignore.rs b/src/test/ui/modules/special_module_name_ignore.rs new file mode 100644 index 0000000000000..cae06b49ee0b7 --- /dev/null +++ b/src/test/ui/modules/special_module_name_ignore.rs @@ -0,0 +1,9 @@ +// run-pass + +#[path = "dummy.rs"] +mod lib; + +#[path = "dummy.rs"] +mod main; + +fn main() {} From c08f460beb86b60aab150f258d96bf99c6eae1b8 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Fri, 15 Apr 2022 16:21:21 -0400 Subject: [PATCH 2/4] tidy --- src/test/ui/modules/dummy.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/modules/dummy.rs b/src/test/ui/modules/dummy.rs index e69de29bb2d1d..831e38292a9ba 100644 --- a/src/test/ui/modules/dummy.rs +++ b/src/test/ui/modules/dummy.rs @@ -0,0 +1 @@ +pub struct Dummy; From f479289e78bc60fbb2aaa3abb33f7726bb12ea89 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Sat, 4 Jun 2022 16:12:45 -0400 Subject: [PATCH 3/4] move dummy test module to auxiliary directory --- src/test/ui/modules/auxiliary/dummy_lib.rs | 2 ++ src/test/ui/modules/dummy.rs | 1 - src/test/ui/modules/special_module_name_ignore.rs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/modules/auxiliary/dummy_lib.rs delete mode 100644 src/test/ui/modules/dummy.rs diff --git a/src/test/ui/modules/auxiliary/dummy_lib.rs b/src/test/ui/modules/auxiliary/dummy_lib.rs new file mode 100644 index 0000000000000..ef805c1f02031 --- /dev/null +++ b/src/test/ui/modules/auxiliary/dummy_lib.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +pub struct Dummy; diff --git a/src/test/ui/modules/dummy.rs b/src/test/ui/modules/dummy.rs deleted file mode 100644 index 831e38292a9ba..0000000000000 --- a/src/test/ui/modules/dummy.rs +++ /dev/null @@ -1 +0,0 @@ -pub struct Dummy; diff --git a/src/test/ui/modules/special_module_name_ignore.rs b/src/test/ui/modules/special_module_name_ignore.rs index cae06b49ee0b7..07cea9b2b05a1 100644 --- a/src/test/ui/modules/special_module_name_ignore.rs +++ b/src/test/ui/modules/special_module_name_ignore.rs @@ -1,9 +1,9 @@ // run-pass -#[path = "dummy.rs"] +#[path = "auxiliary/dummy_lib.rs"] mod lib; -#[path = "dummy.rs"] +#[path = "auxiliary/dummy_lib.rs"] mod main; fn main() {} From 4fdf43f23fbd4fb69960c9136dc796d8e64be785 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Thu, 21 Jul 2022 13:06:08 -0400 Subject: [PATCH 4/4] `special_module_name`: ignore inline modules --- compiler/rustc_lint/src/builtin.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 961e1e9507b97..e9841b7f07132 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3299,7 +3299,11 @@ declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]); impl EarlyLintPass for SpecialModuleName { fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { for item in &krate.items { - if let ast::ItemKind::Mod(..) = item.kind { + if let ast::ItemKind::Mod( + _, + ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _), + ) = item.kind + { if item.attrs.iter().any(|a| a.has_name(sym::path)) { continue; }