Rust

プロジェクトで使用するRustツールチェインのバージョンをチームで共有する

Rust Programming Language Forum Summary
(画像をクリックすると投稿が開きます)

rustup だとプロジェクト内に .rust-toolchain ファイルが置けるよ。するとそのディレクトリでは指定したバージョンの rustc / cargo が使われるようになるんだ。

ちなみに正しくは rust-toolchain ファイル(先頭のドットなし)

こんな方法があるとは知りませんでした。このことは rustup の現在の README にしっかり書いてあるのですが、私が README を最後に読んだのはたぶん1年以上前のこと。その頃にはこの機能はなかったような。

早速、使ってみましょう。すでに rustup で Rust ツールチェインのバージョンを管理している 前提で進めます。

rust-toolchain ファイルを使ってみる

Rust で開発していると時々コンパイラのバージョンを固定したくなることがあります。たとえば使用しているクレートが特定の日にビルドされた nightly でないとコンパイルできないような時です。

バージョンを固定する方法としてよく知られているのはプロジェクトのトップディレクトリ(Cargo.tomlのあるディレクトリ)に移動して、rustup override set <ツールチェインのバージョン> コマンドを実行することです。でもこの方法だと、特にチームで開発している時などメンバー間で徹底するのが難しそうです。また、クレートのバージョンを上げるたびに全員で rustup override しなおすのも非効率です。

rust-toolchain ファイルはそんな時に便利に使えそうです。以下のようにプロジェクトのトップディレクトに移動し、rust-toolchain ファイルを作ります。

$ rustup -V
rustup 1.11.0 (e751ff9f8 2018-02-13)

# テキトーなプロジェクトを作る。
$ cargo new --bin hello
$ cd hello

# プロジェクトを作ったばかりだとデフォルトのツールチェインが
# アクティブになる。(一番下のactive toolchainのところ)
$ rustup show
Default host: x86_64-unknown-freebsd

installed toolchains
--------------------

stable-x86_64-unknown-freebsd
beta-x86_64-unknown-freebsd
nightly-x86_64-unknown-freebsd
1.9.0-x86_64-unknown-freebsd
1.10.0-x86_64-unknown-freebsd
...
1.23.0-x86_64-unknown-freebsd
1.24.1-x86_64-unknown-freebsd

active toolchain
----------------

stable-x86_64-unknown-freebsd (default)
rustc 1.24.1 (d3ae9a9e0 2018-02-27)

# rust-toolchainファイルを作成し、特定のバージョンに固定する。
$ echo 'nightly-2018-03-07' > rust-toolchain

# cargoやrustcを使おうとするとツールチェインが
# 自動的にダウンロードされる。
$ cargo check
info: syncing channel updates for
  'nightly-2018-03-07-x86_64-unknown-freebsd'
info: latest update on 2018-03-07, 
  rust version 1.26.0-nightly (2789b067d 2018-03-06)
info: downloading component 'rustc'
...
info: installing component 'rustc'
info: installing component 'rust-std'
info: installing component 'cargo'
info: installing component 'rust-docs'
   Compiling hello v0.1.0 (file:///.../hello)
    Finished dev [unoptimized + debuginfo] target(s) in 0.14 secs

$ rustup show
...
active toolchain
----------------

nightly-2018-03-07-x86_64-unknown-freebsd (overridden by
  '.../hello/rust-toolchain')
rustc 1.26.0-nightly (2789b067d 2018-03-06)


# 特定のstableリリースに変更する。
$ echo '1.24.1' > rust-toolchain

$ rustup show
...
active toolchain
----------------

1.24.1-x86_64-unknown-freebsd (overridden by
  '.../hello/rust-toolchain')
rustc 1.24.1 (d3ae9a9e0 2018-02-27)

このように rust-toolchain ファイルを使って Rust ツールチェインのバージョンを指定できました。このファイルを Cargo.lock などと共に他のメンバーと共有すれば、同一の環境を得られます。

設定の優先順位

もしすでに rust-toolchain ファイルがあるプロジェクトに対して rustup override set コマンドを実行したらどうなるでしょうか? その答えも README に書かれています。

それぞれの設定は以下の優先順位で使われます(優先度の高いものから低いものへ)

  • cargo +beta などによる明示的な指定
  • RUSTUP_TOOLCHAIN 環境変数
  • ディレクトリごとの上書き rustup override set nightly
  • rust-toolchain ファイル
  • デフォルトのツールチェイン

Rust Epoch Rust: 2018 Edition

余談ですが、近々、Rust Epoch Edition というしくみが導入されるようです(RFC 2052

2018年3月13日修正3月12日のオフィシャルブログの記事では Epoch ではなく、Edition という呼び名が使われていますので、本記事もそれに合わせて修正しました)

2015年5月に1.0がリリースされて以来、stable 版の Rust は高いレベルで後方互換性を維持してきました。過去に開発したプログラムは、Rust コンパイラを当時より新しいバージョンに変えたとしても、ほとんどの場合で問題なくコンパイル・実行できます(warning は出るかもしれませんが)

その一方で、言語仕様やコンパイラの設計は絶え間なく改良されており、リリースから3年近くたった今では、互換性に影響のある変更・新機能も予定されています。

このような非互換の変更を扱うのが edition です。rustc--edition(のような)引数を導入してデフォルトは 2015 にします。デフォルトのまま使っている限り、今まで通り後方互換性が得られます。

非互換の新しい機能を使うためには --edition 2018 などとして明示的に edition を選択します。また Cargo.toml にも edition = "2018" と書けるようして、依存しているクレートのバージョンが選択できるようにしたり、IDE、rustfmt、Clippyなどのツール類の振る舞いを変えたりできるようです。

現在の Rust では nightly に頼る場面も多く rust-toolchain ファイルによる管理が必要ですが、将来は edition による管理に移行できるかもしれません。

次の edition に入る予定の機能は、Epoch.Next Tracking Issue #46889 にまとめられています。

  • 所有権:NLLなど(NLLの日本語による紹介記事
  • トレイトシステムimpl Traitdyn Trait日本語による紹介記事)、一部のクロージャが CloneCopy トレイトを実装、など
  • エラーハンドリング:Option などの型で ? が使用可能に、main() 関数内で ? が使用可能に
  • モジュールシステムmod.rs ファイルが不要になり、crate キーワードが追加される、など

Rust の 2018年のロードマップ には上の(Rust 2018 Edition)をリリースすることが目標の一つに挙げられています。今年も Rust から目が離せませんね。