Rustの名前解決の仕組み: Prelude
Rustにはpreludeという名前解決の仕組みがある。これについて調べる。
preludeとは
preludeとは、crate内の全てのmoduleのスコープに自動的に取り込まれる名前の集まり。名前解決に使われる。
例えば、Box
という名前は (#![no_std]
がない限り) 全てのmoduleで使うことができる。それにもかかわらずself::Box
など存在しない。これはBox
がmodule自体の持つ名前ではなく、preludeに存在する名前であるため。
5種類のprelude
preludeにはいくつか種類がある。
- standard library prelude
- extern prelude
- language prelude
-
macro_use
prelude - tool prelude
standard library prelude
全てのcrateはstandard library preludeを持つ。このstandard library preludeは1つのmoduleから成るが、そのmoduleはcrateのedition ("2015" or "2018" or "2021") と#![no_std]
が適用されているかどうかによって異なる。
#![no_std]
が適用されていない場合はstd::prelude::rust_<edition>
、適用されている場合はcore::prelude::rust_<edition>
がstandard library preludeとなる。
extern prelude
extern crate
やコンパイラーの--extern
オプションでインポートされたcrateたちはextern preludeに追加される。(もしextern crate orig_name as new_name
とaliasでインポートされたらnew_name
の方が追加される。)
core
は常にextern preludeに追加される。#![no_std]
がない限り、std
も追加される。
extern preludeを使った実験
extern preludeを使うとちょっとしたことができる。
2つのファイルを用意する。
// ./main.rs
fn main() {
hi::say_hi();
}
// hi.rs
pub fn say_hi() {
println!("Hi.");
}
hi.rs
をrlibとしてコンパイルし (libhi.rlib
)、main.rs
をコンパイルする際にlibhi.rlib
をhi
crateとしてextern preludeに追加する。
$ rustc --crate-type=rlib ./hi.rs
$ rustc --extern hi=$(pwd)/libhi.rlib main.rs
$ ./main
Hi.
std libraryなどではないものが、ビルトインみたいに使える。
language prelude
language preludeには、型 (bool
, char
, str
, i32
, ...) やattribute (cfg
, derive
, proc_macro
, ...) の名前が含まれる。
macro_use
prelude
macro_use
preludeには、extern crate
のmacro_use
attributeでインポートされた、外部crateのmacroが含まれる。
ここにstd
からエクスポートされた全てのmacroが含まれる。#![no_std]
の場合はstd
ではなくcore
となる。
tool prelude
tool preludeには、#[rustfmt::skip]
や#[clippy::cyclomatic_complexity = "100"]
といったtool attributesの名前が含まれる。
no_implicit_prelude
attribute
crateまたはmoduelに#![no_implicit_prelude]
を適用すると、standard library prelude、extern prelude、tool prelude、macro_use
preludeを自動的にスコープに取り入れることがなくなる。(language preludeには影響なし。) これは子孫moduleにも適用される。
なお、#![no_std]
との名前の一貫性を理由に#![no_implicit_prelude]
を#![no_prelude]
にリネームして、さらに対象のmoduleのみに影響するようにする、というRFC: rust-lang/rfcs#501があるようだ。ただ、このRFCのtracking issueが2022年にcloseされた (能力とやる気のある人待ちのようだ。) ので進捗はないみたい。
Discussion