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

时间:2017-03-18 00:39:01

标签: rust

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

来自my project的示例:

// ...

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

...

at line 13 in the same file,明确使用该功能的同一模块:

// ...

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
}

// ...

然而我得到了编译器警告:

warning: function is never used: `calc_p`, #[warn(dead_code)] on by default
  --> src/spellcheck/corrections.rs:46:1
   |
46 |   fn calc_p(word: &str, dict: &Dictionary) -> f32
   |  _^ starting here...
47 | | {
48 | |     if !dict.contains_key(word) {
49 | |         return 0.0;
50 | |     }
51 | |
52 | |     let total: u32 = dict.values().sum();
53 | |     dict[word] as f32 / total as f32
54 | | }
   | |_^ ...ending here

我想也许是因为模块corrections不公开,但我marked the module as public仍然得到同样的警告。

我尝试使用the playground重现行为,但是如果模块在同一个文件中定义,它似乎可以工作。在a TravisCI build期间,我也会收到警告。

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

我正在使用Rust 1.15 / 1.16。

1 个答案:

答案 0 :(得分:3)

  

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

因为未使用的代码是传递计算,并且无法从包外调用调用该函数的代码。编译器在这里是正确的。

我看到的第一个错误是:

warning: static item is never used: `ALPHABET`, #[warn(dead_code)] on by default
 --> src/spellcheck/edits.rs:3:1

这被定义为:

<强>的src /拼写检查/ edits.rs

static ALPHABET : &'static str = "abcdefghijklmnopqrstuvwxyz";

所以它不公开,只能在模块内部使用。

来自replacesinserts。这两个都来自edits1,一个公共职能部门。包含它的模块(edits)是否公开?

<强>的src /拼写检查/ mod.rs

mod edits;
pub mod corrections;
pub mod dictionary;

不,不是。那么调用edits1的位置是什么? kodecheck_spellcheck::spellcheck::corrections::create_candidates,非公共职能。这由公共模块suggest_corrections内的公共函数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;

阿。无论出于何种原因,您已决定在包中引入完全嵌套的私有模块spellcheck(这就是为什么之前的完整路径为kodecheck_spellcheck::spellcheck::corrections::create_candidates)。

据此,我们可以看到无法从包装箱外部访问kodecheck_spellcheck::spellcheck ;它不是pub

让我们创建一个使用包的示例。这是查看它是否真实并且您可以轻松测试自己的最佳方式:

<强>实例/ foo.rs

extern crate kodecheck_spellcheck;

fn main() {
    kodecheck_spellcheck::spellcheck::corrections::create_candidates();
}

编译它有错误:

error: module `spellcheck` is private
 --> examples/foo.rs:4:5
  |
4 |     kodecheck_spellcheck::spellcheck::corrections::create_candidates();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我们还可以创建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() {}

请注意,这与您的示例不同,因为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();
        }
    }
}

因为所有代码都是私有模块,所以没有在这个crate之外可以调用里面的任何内容。因此,每种方法都无法实现。

要解决此问题,我建议将 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 {
    // ...

rustfmt这样的工具可以帮助您应用正确的风格。