LoginSignup
52
45

More than 5 years have passed since last update.

Rust 1.13.0 がリリースされました

Last updated at Posted at 2016-11-11

Rust 1.13.0 が日本時間の本日(2016年11月11日)リリースされました。Rust は、安全性、スピード、並列プログラミングにフォーカスした、システムプログラミング向けの言語です。

また同時に、次のバージョン 1.14.0 がベータ版になりました。1.14.0 は、6週間後の2016年12月23日(日本時間)にリリースされる予定です。

これから Rust を始める人には、以下の日本語翻訳版のドキュメントをおすすめします。

以下、リリースアナウンスに書かれている内容から、主なものを紹介します。(この記事は抄訳です)


このところ、Rust について多忙な時期が続いています。短い期間に、RustConfRustFestRust Belt Rust という3つの Rust カンファレンスが開催され、皆さんとの楽しい時を過ごすことができました。世界中の Rustaceans と会うのは楽しいものですし、リアルでお会いするのは初めての人もいました! 私たちは Rust の今後について アイデアを出し合い、それを反映した 2017年のロードマップ を作成しました。また、皆さんからの要望 が多かった IDE のサポートを向上するツール も開発しています。

このような時期でも、私たちは、新しい要素がぎっしりつまったリリースをまとめ上げることができました。

1.13.0 安定版の内容

この 1.13 リリースには、言語に対するいくつかの拡張が含まれています。長く待ち望まれた ? 演算子。コンパイル時間の改善。Cargo や標準ライブラリに対する小さな機能追加などなど。また、このリリースには、ドキュメントやエラーメッセージに対して、リリースノートに載らなかった人たちも含む多くのコントリビューターから、数多くの細やかな改良が施されました。

このリリースには Cargo に対する重要なセキュリティアップデートも含まれています。これは、最近セキュリティアップデートが公開された curl と OpenSSL に関するものです。詳しくは、curl と OpenSSL のリリースアナウンスを参照してください。

? 演算子

Rust に言語レベルの演算子 ? が追加されました。これは視覚的なノイズを減らし、エラー処理をより快適にしてくれます。例として、ファイルからデータを読み込む関数を見てみましょう。

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("username.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

この関数では、ファイルのオープンとデータ読み込みの2つの場所でエラー処理を行っています。エラーが起こったら、この関数から Err<io::Error> 型の値を返したいので、それぞれの I/O 操作の戻り値に対して match による場合分けをしています。このような、エラーを呼び出し元に伝えるというシンプルな例でも、場合分けという単調なボイラープレートが繰り返し現れ、読みにくさにつながっています。

? を使うと、こう変わります。

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("username.txt")?;
    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}

? は先ほどの match 式全体の省略形となっています。つまり、?Result 値に適用され、もしそれが Ok だったなら、アンラップした値を返します。もしそれが Err だったなら、いまいる関数からリターンします。これからは ? という文字を書くだけで、この場所で標準的なエラー処理を行い、呼び出し元にエラーを返すことを表明できます。

もしあなたが経験豊かな Rustacean なら、これが Rust 1.0 から使われてきた try! マクロと同じであることに気づくかもしれません。その通りです。1.13 以前では、同じ関数をこう書いたかもしれません。

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = try!(File::open("username.txt"));
    let mut s = String::new();

    try!(f.read_to_string(&mut s));

    Ok(s)
}

ではなぜ、すでにマクロがあるのに、言語を拡張したのでしょうか? これにはいくつかの理由があります。まず、これまでに try! が非常に役立つことが証明され、しばしば Rust のイディオムとして使われてきたことがあります。あまりにもよく使われるので、私たちは、これに対するシンタックスシュガー(糖衣構文)を持つべきだと考えるようになりました。これは、Rust のような強力なマクロシステムを持つことの利点の一つです。マクロによって、言語に手を入れることなく文法を拡張でき、もしそれが非常に有用なら、言語になにか不足している機能があることを示しています。try! から ? への進化は、その好例です。

また、このようなシンタックスシュガーが特に活かされる場面があります。以下のように、try! が入れ子になってたら?

try!(try!(try!(foo()).bar()).baz())

これと比べて、どうでしょうか?

foo()?.bar()?.baz()?

最初の例では、コードのメインのパス(エラーがなかった時のパス)が、わかりづらくなっています。foobarbaz のような呼び出しチェインとエラー処理の組み合わせは、ビルダーパターンでよく使われます。

最後に、専用の構文をもたせたことで、将来 ? に関連するエラーメッセージをもっと親切にできるかもしれません。このようなエラーメッセージのカスタマイズは、マクロ展開で得られたコードに対しては、一般的に実現が困難です。(とはいえ、今回のリリースでは、? に関連するエラーメッセージは、改良が必要なレベルです)

これはとても小さな機能ですが、これまで nightly 版で使ってきた経験から、?try! マクロに対する、エルゴノミック(使いやすさ)上の、確固とした改良となりそうです。

? についての詳細は、RFC 243 を参照してください。

パフォーマンスの改善

ここしばらく、私たちは、コンパイラーのパフォーマンス改善に注力しています。このリリースでも良いニュースがありますし、しばらくはこうしたニュースが続くでしょう。

(これ以降は、数日以内を目標に翻訳します)

Mark Simulacrum and Nick Cameron have been refining perf.rust-lang.org, our tool for tracking compiler performance. It runs the rustc-benchmarks suite regularly, on dedicated hardware, and tracks the results over time. This tool records the results for each pass in the compiler and is used by the compiler developers to narrow commit ranges of performance regressions. It's an important part of our toolbox!

We can use this tool to look at a graph of performance over the 1.13 development cycle, shown below. This cycle covered the dates from August 16 through September 29 (the graph begins from Augest 25th though and is filtered in a few ways to eliminate bogus, incomplete, or confusing results). There appear to be some big reductions, which are quantified on the corresponding statistics page.


Performance graph


The big improvement demonstrated in the graphs, on September 1, is from an optimization from Niko to cache normalized projections during translation. That is to say, during generation of LLVM IR, the compiler no longer recomputes concrete instances of associated types each time they are needed, but instead reuses previously-computed values. This optimization doesn't affect all code bases, but in code bases that exhibit certain patterns, like futures-rs, where debug mode build-time improved by up to 40%, you'll notice the difference.

Another such optimization, that doesn't affect every crate but does affect some in a big way, came from Michael Woerister, and improves compile time for crates that export many inline functions. When a function is marked #[inline], in addition to translating that function for use by the current crate, the compiler stores its MIR representation in the crate rlib, and translates the function to LLVM IR in every crate that calls it. The optimization Michael did is obvious in retrospect: there are some cases where inline functions are only for the consumption of other crates, and never called from the crate in which they are defined; so the compiler doesn't need to translate code for inline functions in the crate they are defined unless they are called directly. This saves the cost of rustc converting the function to LLVM IR and LLVM optimizing and converting the function to machine code.

In some cases this results in dramatic improvements. Build times for the ndarray crate improved by 50%, and in the (unreleased) winapi 0.3 crate, rustc now emits no machine code at all.

But wait, there's more still! Nick Nethercote has turned his focus to compiler performance as well, focusing on profiling and micro-optimizations. This release contains several fruits of his work, and there are more in the pipeline for 1.14.

その他の目立った変更点

This release contains important security updates to Cargo, which depends on curl and OpenSSL, which both published security updates recently. For more information see the respective announcements for curl 7.51.0 and OpenSSL 1.0.2j.

Macros can now be used in type position (RFC 873), and attributes can be applied to statements (RFC 16):

// Use a macro to name a type
macro_rules! Tuple {
    { $A:ty,$B:ty } => { ($A, $B) }
}

let x: Tuple!(i32, i32) = (1, 2);
// Apply a lint attribute to a single statement
#[allow(uppercase_variable)]
let BAD_STYLE = List::new();

Inline drop flags have been removed. Previously, in case of a conditional move, the compiler would store a "drop flag" inline in a struct (increasing its size) to keep track of whether or not it needs to be dropped. This means that some structs take up some unexpected extra space, which interfered with things like passing types with destructors over FFI. It also was a waste of space for code that didn't have conditional moves. In 1.12, MIR became the default, which laid the groundwork for many improvements, including getting rid of these inline drop flags. Now, drop flags are stored in an extra slot on the stack frames of functions that need them.

1.13 contains a serious bug in code generation for ARM targets using hardware floats (which is most ARM targets). ARM targets in Rust are presently in our 2nd support tier, so this bug was not determined to block the release. Because 1.13 contains a security update, users that must target ARM are encouraged to use the 1.14 betas, which will soon get a fix for ARM.

言語の安定化

ライブラリの安定化

Cargo の機能

See the detailed release notes for more.

52
45
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
45