Rollup merge of #94467 - ibraheemdev:master, r=pnkfelix

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.
This commit is contained in:
Matthias Krüger 2022-09-01 21:37:07 +02:00 committed by GitHub
commit da1d738601
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 135 additions and 0 deletions

View file

@ -3172,3 +3172,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
}
}
}
}
}

View file

@ -133,6 +133,7 @@ macro_rules! early_lint_passes {
UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode,
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
NonCamelCaseTypes: NonCamelCaseTypes,

View file

@ -0,0 +1,2 @@
#[allow(dead_code)]
pub struct Dummy;

View file

@ -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() {}

View file

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

View file

@ -0,0 +1,9 @@
// run-pass
#[path = "auxiliary/dummy_lib.rs"]
mod lib;
#[path = "auxiliary/dummy_lib.rs"]
mod main;
fn main() {}