编译器警告实际使用的私有函数的未使用代码

Max*_*Max 3 rust

我开始将我的一个项目的代码分组到模块文件中。我遇到了很多关于这些模块中函数未使用代码的警告,但这些函数实际上已被使用(在模块内私有)。

我的项目的一个例子:

// ...

// 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。

She*_*ter 5

为什么该函数被标记为未使用,尽管它实际上在同一模块的同一文件中使用?

因为未使用的代码是传递计算,并且调用该函数的代码不能从 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这样的工具将帮助您应用正确的样式。