warning: function `xxx` is never used

warning: struct `Xxx` is never used

warning: enum `Xxx` is never used

未使用のアイテムがあると警告が出る。

当然の機能なのだが、Rust 特有の落し穴がいくつかある。

パターン

パターン A

基本形

そのアイテムが実際にどこからも使われていないパターン。

サンプル


pub fn main() {
	// nop.
}

fn unused() {
	// nop.
}

warning: function `unused` is never used
 --> src\main.rs:4:4
  |
4 | fn unused() {
  |    ^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

パターン B

使用元が未使用

そのアイテムを使っているアイテムがどこからも使われていないパターン。

サンプル


pub fn main() {
    // nop.
}

fn unused() {
    unused_sub();
}

fn unused_sub() {
    // nop.
}

warning: function `unused` is never used
 --> src\main.rs:5:4
  |
5 | fn unused() {
  |    ^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: function `unused_sub` is never used
 --> src\main.rs:9:4
  |
9 | fn unused_sub() {
  |    ^^^^^^^^^^

パターン C

単体テストが関係

そのアイテムが単体テスト以外から使われていないと発生する。

サンプル


#[test]
fn test() {
    test_helper();
}

fn test_helper() {
    // nop.
}

warning: function `test_helper` is never used
 --> src\lib.rs:6:4
  |
6 | fn test_helper() {
  |    ^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

解決策

対象のアイテムに #[cfg(test)] 属性を付加すれば良い。


#[test]
fn test() {
    test_helper();
}

#[cfg(test)]
fn test_helper() {
    // nop.
}

パターン D

統合テストが関係

Rust の統合テストでは、tests ディレクトリ直下のファイルがそれぞれ独立したクレートとして認識される。そのため、テストヘルパ系のアイテムについては、tests ディレクトリ直下の全てのファイルから使われていないと、クレート内に使われていないアイテムがあると認識されてしまう。

サンプル

my_lib/tests/common.rs

pub fn test_helper1() {}
pub fn test_helper2() {}
my_lib/tests/a.rs

mod common;
use common::*;

#[test]
fn test() {
    test_helper1();
}
my_lib/tests/b.rs

mod common;
use common::*;

#[test]
fn test() {
    test_helper1();
    test_helper2();
}

warning: function `test_helper2` is never used
 --> tests\common.rs:2:8
  |
2 | pub fn test_helper2() {}
  |        ^^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

解決策

お勧めは解決策 3 の方法。

解決策 1
テストヘルパのクレート化
解決策 2
テストヘルパのダミー公開
解決策 3
ディレクトリ構成の変更

テストヘルパのクレート化

テストヘルパを全て独立したクレートに移動する。

この方法は大げさでやや手間がかかるのが問題点。

テストヘルパのダミー公開

使用していないテストヘルパを pub use で公開する。

テストコードは外部から使えないため、この公開は問題にならない。

この方法はその場しのぎだが手間はかからない。

ディレクトリ構成の変更

ディレクトリ構成を変更してテストを一つのクレートにまとめる。

これには tests の中で main.rs を使えばよい (参考: パッケージ構成の公式資料)。

例えば、前述の例の場合、以下のようなディレクトリ構成にすればよい。

my_lib
├─ src
│  └─ ...
└─ tests
   └─ it
      ├─ main.rs
      ├─ a.rs
      ├─ b.rs
      └─ common.rs

警告の抑制

本質的な方法ではないが、強制的に警告を抑制する方法がいくつかある。

アンダースコアの使用

アイテム名をアンダースコア '_' で始めると警告がでなくなる。


pub fn main() {
    // nop.
}

fn _unused() {
    // nop.
}

#[allow(dead_code)]

警告を抑制したい箇所に #[allow(dead_code)] を付加する。

個別指定

アイテムごとに個別指定する方法。


pub fn main() {
    // nop.
}

#[allow(dead_code)]
fn unused() {
    // nop.
}

一括指定

ファイルやモジュールに所属するアイテムを一括指定する方法。


fn main() {}

#[allow(dead_code)]
mod my_mod {
    fn unused1() {}
    fn unused2() {}
}