Skip to content

Commit

Permalink
Rollup merge of rust-lang#94467 - ibraheemdev:master, r=pnkfelix
Browse files Browse the repository at this point in the history
Add `special_module_name` lint

Declaring `lib` as a module is one of the most common beginner mistakes when trying to setup a binary and library target in the same crate. `special_module_name` lints against it, as well as `mod main;`
```
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

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
   ```

Note that the help message is not the best in that it doesn't provide an example of an import path (`the_actual_crate_name::`), and doesn't check whether the current file is part of a library/binary target to provide more specific error messages. I'm not sure where this lint would have to be run to access that information.
  • Loading branch information
matthiaskrgr authored Sep 1, 2022
2 parents fb88811 + 4fdf43f commit 96ae006
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
78 changes: 78 additions & 0 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3173,3 +3173,81 @@ 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(
_,
ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
) = 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
}
}
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ macro_rules! early_lint_passes {
UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode,
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
NonCamelCaseTypes: NonCamelCaseTypes,
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/modules/auxiliary/dummy_lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[allow(dead_code)]
pub struct Dummy;
8 changes: 8 additions & 0 deletions src/test/ui/modules/special_module_name.rs
Original file line number Diff line number Diff line change
@@ -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() {}
37 changes: 37 additions & 0 deletions src/test/ui/modules/special_module_name.stderr
Original file line number Diff line number Diff line change
@@ -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`.
9 changes: 9 additions & 0 deletions src/test/ui/modules/special_module_name_ignore.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// run-pass

#[path = "auxiliary/dummy_lib.rs"]
mod lib;

#[path = "auxiliary/dummy_lib.rs"]
mod main;

fn main() {}

0 comments on commit 96ae006

Please sign in to comment.