項目23:ワイルドカードインポートを避けよう
https://effective-rust.com/wildcard.html
ワイルドカードインポート(グローバルインポート)を用いると、外部クレートの 破壊的変更 でない変更によって、ローカルで使用している名前と衝突 し、コードが破壊される可能性がある
通常、ワイルドカードインポートされた名前は優先度が低いため、ローカルの名前が優先される
code:rs
use bytes::*;
struct Bytes(Vec<u8>);
しかし、外部クレートで追加された新しいメソッド名が既存のメソッド名と衝突した場合
code:rs
trait BytesLeft {
fn remaining(&self) -> usize;
}
impl BytesLeft for &u8 {
fn remaining(&self) -> usize {
self.len()
}
}
コンパイラ はどちらのメソッドを意図しているのか判断できない ため、コンパイルエラーを吐く
code:rs
let arr = 1u8, 2u8, 3u8;
let v = &arr1..;
assert_eq!(v.remaining(), 2);
上記を踏まえると、「自分で制御できなクレートからのワイルドカードインポートは避けるべき」
例外
モジュールをコード分割に利用しているコードで、内部モジュールの公開アイテムを再エクスポートする場合
code:rs
mod thing;
pub use thing::*;
prelude モジュールを提供している外部クレートの場合
prelude は明示的にワイルドカードインポートされるよう意図されている
use thing::prelude::*;
上述の問題は起こり得るが、prelude のアイテムは注意深く選択されているため、問題が起こるリスクよりも 利便性 が上回る
「ワイルドカードインポートする依存ライブラリを特定のバージョンに固定する」ことでも回避可能
radish-miyazaki.icon
個人的にはどのアイテムがどのクレート由来なのか分からないので、ワイルドカードインポートはしないで欲しい…
特に Rust は依存クレートが多くなる傾向になるため
#Rust #Effective_Rust_―_Rustコードを改善し、エコシステムを最大限に活用するための35項目