我开始将我的一个项目的代码分组到模块文件中。我遇到了很多关于这些模块中函数未使用代码的警告,但这些函数实际上已被使用(在模块内私有)。
我的项目的一个例子:
// ...
// Line 46:
fn calc_p(word: &str, dict: &Dictionary) -> f32
{
if !dict.contains_key(word) {
return 0.0;
}
let total: u32 = dict.values().sum();
dict[word] as f32 / total as f32
}
...
Run Code Online (Sandbox Code Playgroud)
但在同一文件、同一模块的第 13 行,该函数显然被使用了:
// ...
pub fn suggest_corrections(to_be_corrected: &str, dict: &Dictionary) -> Vec<(f32, String)>
{
let candidates = create_candidates(to_be_corrected, dict);
let mut weighted_candidates = candidates
.into_iter()
.map(|w| (calc_p(&w, dict), w)) // Line 13 - calc_p used here
.collect::<Vec<_>>();
weighted_candidates.sort_by(|a, b| b.partial_cmp(a).unwrap());
weighted_candidates
}
// ...
Run Code Online (Sandbox Code Playgroud)
但我收到编译器警告:
// ...
// Line 46:
fn calc_p(word: &str, dict: &Dictionary) -> f32
{
if !dict.contains_key(word) {
return 0.0;
}
let total: u32 = dict.values().sum();
dict[word] as f32 / total as f32
}
...
Run Code Online (Sandbox Code Playgroud)
我想也许是因为该模块corrections不是公共的,但我也将该模块标记为公共,但仍然收到相同的警告。
我尝试使用Playground重现该行为,但如果该模块是在同一文件中定义的,那么它似乎可以工作。在TravisCI 构建期间,这些警告也会发生在我身上。
为什么该函数被标记为未使用,尽管它实际上在同一模块的同一文件中使用?
我正在使用 Rust 1.15 / 1.16。
为什么该函数被标记为未使用,尽管它实际上在同一模块的同一文件中使用?
因为未使用的代码是传递计算,并且调用该函数的代码不能从 crate 外部调用。编译器在这里是正确的。
我看到的第一个错误是:
warning: static item is never used: `ALPHABET`, #[warn(dead_code)] on by default
--> src/spellcheck/edits.rs:3:1
Run Code Online (Sandbox Code Playgroud)
其定义为:
src/拼写检查/edits.rs
static ALPHABET : &'static str = "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
所以它不是公共的,只能在模块内部使用。
它是从replaces和调用的inserts。这两个都是从edits1公共函数 中使用的。包含它的模块 ( edits) 是公共的吗?
src/拼写检查/mod.rs
mod edits;
pub mod corrections;
pub mod dictionary;
Run Code Online (Sandbox Code Playgroud)
不,事实并非如此。那么edits1从哪里调用呢?kodecheck_spellcheck::spellcheck::corrections::create_candidates,非公共函数。suggest_corrections这是由public 模块内的公共函数调用的corrections。
我们去树上看看...
src/lib-spellcheck.rs
// @FIXME do we really need this here or move to sub-modules?
#[macro_use]
extern crate nom;
extern crate regex;
mod spellcheck;
Run Code Online (Sandbox Code Playgroud)
啊。无论出于何种原因,您决定在板条箱内引入一个完全嵌套的私有模块spellcheck(这就是为什么前面的完整路径是kodecheck_spellcheck::spellcheck::corrections::create_candidates)。
由此可见,无法kodecheck_spellcheck::spellcheck 从 crate 外部访问;它不是pub。
让我们创建一个使用该板条箱的示例。这是检验它是否真实的最佳方法,并且您可以轻松地测试自己:
示例/foo.rs
extern crate kodecheck_spellcheck;
fn main() {
kodecheck_spellcheck::spellcheck::corrections::create_candidates();
}
Run Code Online (Sandbox Code Playgroud)
编译此错误:
static ALPHABET : &'static str = "abcdefghijklmnopqrstuvwxyz";
Run Code Online (Sandbox Code Playgroud)
我们还可以创建一个MCVE:
mod spellcheck {
mod edits {
static ALPHABET: &'static str = "";
pub fn edits1() {
println!("{}", ALPHABET);
}
}
pub mod corrections {
pub fn create_candidates() {
::spellcheck::edits::edits1();
}
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
请注意,这与您的示例不同,因为main它是空的。您的库箱没有main调用任何内容的方法。您还可以明确指定它是一个库箱,但这不太为人所知:
#![crate_type="lib"]
mod spellcheck {
mod edits {
static ALPHABET: &'static str = "";
pub fn edits1() {
println!("{}", ALPHABET);
}
}
pub mod corrections {
pub fn create_candidates() {
::spellcheck::edits::edits1();
}
}
}
Run Code Online (Sandbox Code Playgroud)
因为所有代码都在一个私有模块中,所以该板条箱之外的任何内容都不能调用该板条箱内的任何内容。因此每个方法都是不可达的。
要修复它,我建议将src/spellcheck/mod.rs合并到src/lib-spellcheck.rs中。您也可以将模块公开,但我认为没有理由拥有额外的模块。
我也认为没有理由将src/lib.rs重命名为src/lib-spellcheck.rs;将其保留为lib.rs更为惯用。
此外,您应该继续并熟悉 Rust 风格。大括号与签名在同一行:
fn calc_p(word: &str, dict: &Dictionary) -> f32 {
// ...
Run Code Online (Sandbox Code Playgroud)
像rustfmt这样的工具将帮助您应用正确的样式。