Skip to content

Commit aad5daa

Browse files
authored
Rollup merge of rust-lang#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.
2 parents 74f600b + f479289 commit aad5daa

File tree

6 files changed

+131
-0
lines changed

6 files changed

+131
-0
lines changed

compiler/rustc_lint/src/builtin.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3185,3 +3185,77 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
31853185
}
31863186
}
31873187
}
3188+
3189+
declare_lint! {
3190+
/// The `special_module_name` lint detects module
3191+
/// declarations for files that have a special meaning.
3192+
///
3193+
/// ### Example
3194+
///
3195+
/// ```rust,compile_fail
3196+
/// mod lib;
3197+
///
3198+
/// fn main() {
3199+
/// lib::run();
3200+
/// }
3201+
/// ```
3202+
///
3203+
/// {{produces}}
3204+
///
3205+
/// ### Explanation
3206+
///
3207+
/// Cargo recognizes `lib.rs` and `main.rs` as the root of a
3208+
/// library or binary crate, so declaring them as modules
3209+
/// will lead to miscompilation of the crate unless configured
3210+
/// explicitly.
3211+
///
3212+
/// To access a library from a binary target within the same crate,
3213+
/// use `your_crate_name::` as the path path instead of `lib::`:
3214+
///
3215+
/// ```rust,compile_fail
3216+
/// // bar/src/lib.rs
3217+
/// fn run() {
3218+
/// // ...
3219+
/// }
3220+
///
3221+
/// // bar/src/main.rs
3222+
/// fn main() {
3223+
/// bar::run();
3224+
/// }
3225+
/// ```
3226+
///
3227+
/// Binary targets cannot be used as libraries and so declaring
3228+
/// one as a module is not allowed.
3229+
pub SPECIAL_MODULE_NAME,
3230+
Warn,
3231+
"module declarations for files with a special meaning",
3232+
}
3233+
3234+
declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]);
3235+
3236+
impl EarlyLintPass for SpecialModuleName {
3237+
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
3238+
for item in &krate.items {
3239+
if let ast::ItemKind::Mod(..) = item.kind {
3240+
if item.attrs.iter().any(|a| a.has_name(sym::path)) {
3241+
continue;
3242+
}
3243+
3244+
match item.ident.name.as_str() {
3245+
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
3246+
lint.build("found module declaration for lib.rs")
3247+
.note("lib.rs is the root of this crate's library target")
3248+
.help("to refer to it from other targets, use the library's name as the path")
3249+
.emit()
3250+
}),
3251+
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
3252+
lint.build("found module declaration for main.rs")
3253+
.note("a binary crate cannot be used as library")
3254+
.emit()
3255+
}),
3256+
_ => continue
3257+
}
3258+
}
3259+
}
3260+
}
3261+
}

compiler/rustc_lint/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ macro_rules! early_lint_passes {
130130
UnusedBraces: UnusedBraces,
131131
UnusedImportBraces: UnusedImportBraces,
132132
UnsafeCode: UnsafeCode,
133+
SpecialModuleName: SpecialModuleName,
133134
AnonymousParameters: AnonymousParameters,
134135
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
135136
NonCamelCaseTypes: NonCamelCaseTypes,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[allow(dead_code)]
2+
pub struct Dummy;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mod lib;
2+
//~^ WARN found module declaration for lib.rs
3+
//~| ERROR file not found for module `lib`
4+
mod main;
5+
//~^ WARN found module declaration for main.rs
6+
//~| ERROR file not found for module `main`
7+
8+
fn main() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0583]: file not found for module `lib`
2+
--> $DIR/special_module_name.rs:1:1
3+
|
4+
LL | mod lib;
5+
| ^^^^^^^^
6+
|
7+
= help: to create the module `lib`, create file "$DIR/lib.rs" or "$DIR/lib/mod.rs"
8+
9+
error[E0583]: file not found for module `main`
10+
--> $DIR/special_module_name.rs:4:1
11+
|
12+
LL | mod main;
13+
| ^^^^^^^^^
14+
|
15+
= help: to create the module `main`, create file "$DIR/main.rs" or "$DIR/main/mod.rs"
16+
17+
warning: found module declaration for lib.rs
18+
--> $DIR/special_module_name.rs:1:1
19+
|
20+
LL | mod lib;
21+
| ^^^^^^^^
22+
|
23+
= note: `#[warn(special_module_name)]` on by default
24+
= note: lib.rs is the root of this crate's library target
25+
= help: to refer to it from other targets, use the library's name as the path
26+
27+
warning: found module declaration for main.rs
28+
--> $DIR/special_module_name.rs:4:1
29+
|
30+
LL | mod main;
31+
| ^^^^^^^^^
32+
|
33+
= note: a binary crate cannot be used as library
34+
35+
error: aborting due to 2 previous errors; 2 warnings emitted
36+
37+
For more information about this error, try `rustc --explain E0583`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-pass
2+
3+
#[path = "auxiliary/dummy_lib.rs"]
4+
mod lib;
5+
6+
#[path = "auxiliary/dummy_lib.rs"]
7+
mod main;
8+
9+
fn main() {}

0 commit comments

Comments
 (0)