よくある質問

このページはプログラミング言語Rustへのよくある質問に答えるために存在しています。 完璧な言語へのガイドでも、言語を教えるためのツールでもありません。 Rustコミュニティの人が出喰わすよく繰り返される質問への参考となる回答であり、Rustの設計上の判断の背後にある論拠を明らかにするためのものです。

もしよくある、あるいは重要な質問で、不当にここに掲載されていないと感じるものがあるなら気軽に修正して貢献して下さい

Rustプロジェクト

プロジェクトのゴールは何ですか?

安全で、並行で、実用的なシステムプログラミング言語を設計し実装することです。

Rustは同程度の抽象レベルと効率性を兼ね備えた言語が満足に存在しないため存在しています。特に、以下の点が満足出来ません

  1. 安全性への考慮がほとんど払われていない
  2. 並行性のサポートが貧弱
  3. 実用性に乏しい
  4. リソースへの制御が限られている

Rustはこれらの4つの点を改善しつつ効率性と快適なレベルの抽象を提供するための新たな選択肢となるために存在しています。

プロジェクトはMozillaにコントロールされていますか?

いいえ。Rustは2006年にGraydon Hoareの趣味のプロジェクトとして始まり、3年間そのままでした。 Mozillaは2009年に基本的なテストが通り、コアコンセプトをデモンストレーション出来るようになるくらい言語が成熟してから関わり始めました。 今でもMozillaによる支援を受けていますが、Rustは世界中多種多様な場所からの熱烈なファンによる様々なコミュニティにより開発されています。 RustチームにはMozillaの職員もいればMozillaと関わりのない人もおり、GitHubの rust には1,900もの貢献者がいます。

プロジェクト自治が回っている限り、Rustはプロジェクトのヴィジョンと優先順位を定めグローバルな視点で舵を切る役割を持つコアチームによって管理されます。 また、言語コア、コンパイラ、Rustのライブラリ、Rustのツール、公式のRustコミュニティのモデレーションなどの領域で開発を先導し育成するためのサブチームも存在します。 それぞれの領域でのデザインはRFCプロセスを通じて拡張されています。 RFCを必要としない変更についてはrustc レポジトリのプルリクエストで決定がなされています。

Rustで目指さないものは何ですか。

  1. 最先端すぎる技術を採用したりはしません。古く、確立された技術の方を好みます。
  2. 表現力、ミニマリズム、エレガントさを他のゴールより重んじることはしません。あれば望ましいですが、下位のゴールです。
  3. C++をはじめ、他の言語の全ての機能群をカバーすることは意図しません。Rustは多くの人が使う機能を提供します。
  4. 100%静的、100%安全、100%反映的、あるいは他のどんな性質についても金科玉条にするつもりはありません。トレードオフが存在します。
  5. Rustが「ありとあらゆるプラットフォーム」で走ることは要求しません。最終的には不必要な妥協なしに広く使われているハードウェア、ソフトウェアプラットフォームで動くべきです。

MozillaはどのプロジェクトでRustを使っていますか?

メインのプロジェクトはServoで。Mozillaが開発中の実験的なブラウザエンジンです。Rustのコンポーネントの統合の作業もしています。

Rustの大きなプロジェクトの例は何がありますか?

現在、2つの大きなオープンソースプロジェクトがあります。ServoRustコンパイラ自身です。

他に誰がRustを使っていますか?

多くの団体が使っておりその数は増え続けています!

どうやったら簡単にRustを試せますか。

最も簡単にRustを試せるのはplaypenを使うことです。オンラインでRustを書いて実行出来ます。 お使いのシステムで使いたければインストールして「プログラミング言語Rust」の数当てゲームのチュートリアルをやりましょう。

Rustで問題に遭遇したときにどうやって助けを求められますか。

いくつか方法があります。

何故Rustはずっと変わり続けていたのですか?

Rustは安全でありながら使いやすいシステムプログラミング言語を目指して発足しました。 このゴールを追求するために多くのアイディアを探求し、そのうちのいくつかは残り(ライフタイムやトレイト)ましたが、捨てられたもの(タイプステートシステム、グリーンスレッド)もあります。 また、1.0への道中で標準ライブラリは初期の設計をRustの機能に合わせ、良質で一貫性のとれたクロスプラットフォームなAPIへ更新するために書き換えられました。 今ではRustは1.0へ達したので「安定」したことが保証されています。そして進化しつづけながらも現在動いているRustのコードは将来のリリースでも動き続ける筈です。

Rustの言語バージョンの仕組みはどうなっていますか?

Rustの言語バージョニングはSemVerに従っていて、マイーバージョンでのstableなAPIの後方互換性を保たない変更はコンパイラバグの修正、セーフティホールへのパッチ、ディスパッチあるいは型推論をアノテーションが必要なようにすることのみ許されています。 マイナーバージョンの変更での詳細なガイドラインは承認済みRFCのlanguagestandard libraryで確認出来ます。

Rustは3つの「リリースチャネル」を維持しています。stable、beta、nightlyです。 stableとbetaは6週間毎に更新されていて、そのときのnightlyがbetaに、betaがstableになります。 言語や標準ライブラリのunstableとマークされた機能やフィーチャゲートで隠されたフィーチャはnightlyのリリースチャネルでのみ使えます。 新しい機能はunstableとして導入され、コアチームと関係したサブチームに承認されたら「開放」されます。 この方法でstableチャネルに強に後方互換性を保証しつつ実験することが出来ます。

さらなる詳細へはRustブログの投稿、“Stability as a Deliverable.”をお読み下さい。

不安定な機能やフィーチャをbeta、あるいはstableチャネルで使うことは出来ますか?

いいえ、出来ません。 Rustはbetaとstableチャネルで提供される機能の安定性を強く保証するために多大な努力をしています。 何かが不安定なら、このような保証が崩れてしまいますし、保証に頼っている人たちにも不安定さを提供したくはありません。 このような理由から安定性を求める人へ強い保証を維持しつつ、nightlyのリリースチャネルで野良に変更を試すようになりました。

物事は常に安定になり続けていて、betaとstableチャネルは、偶にbetaに修正が入りつつ6週間毎に更新されています。 nightlyにある何かの機能やフィーチャを使いたくて待ち続けているのならイシュートラッカー上のB-unstableタグを確認するとトラッキングイシューを発見出来ます。

「フィーチャゲート」とは何ですか?

「フィーチャゲート」はRustがコンパイラ、言語、標準ライブラリのフィーチャを安定化させるために使う仕組みです。 「ゲート」されているフィーチャはnightlyリリースチャネルでのみアクセス可能で、#[feature] アトリビュートか -Z unstable-options コンパイラ引数で明示的に有効にしたときのみ使えます。 フィーチャが安定化されたら、stableのリリースチャネルで使えるようになり、明示的に有効にする必要はなくなります。 その時点でフィーチャは「開放」されたと考えられます。 フィーチャゲートのおかげで開発中の実験的な機能をstableの言語で使えるようになる前にテスト出来ます。

何故MIT/ASL2のデュアルライセンスなのですか?

Apacheライセンスは特許侵害についての重要な保護を含んでいます、しかしそれはGPLのバージョン2と非互換です。 RustをGPL2と一緒に使うときの問題を回避するために代替としてMITでもライセンシングされています。

何故MPL、あるいは三重ライセンスではなくBSDスタイルの許容的ライセンスなのですか?

これは一部はオリジナルの開発者(Graydon)の好みで、一部は言語はWebブラウザなどの製品と比べて広いユーザ、多様な組み込みやエンドユーズがあることが多いからです。 我々は可能な限り多くのこれらの潜在的なコントリビュータにアピールしていきたいと思っています。

パフォーマンス

Rustはどのくらい速いですか?

速いです!Rustの性能はすでに、多数のベンチマークについて、自然に書かれたC/C++に匹敵しています(Benchmarks Gameなど)。

RustはC++と同じように、基本原則の1つとしてゼロコスト抽象化を掲げています。つまり、Rustの抽象には、全体的な性能にペナルティを課すようなものはなく、ランタイムシステムのオーバーヘッドもないということです。

RustはLLVMの上に構築されており、LLVMから見てClangっぽく見えるように頑張っているので、LLVMの性能が向上したらRustの性能向上にもつながります。長い目でみれば、Rustの型システムはより豊富な情報をもつので、C/C++のコードでは困難か不可能な最適化も可能になるはずです。

Rustにガベージコレクションはありますか?

ありません。ガベージコレクションなしでメモリ安全性(セグメンテーションフォールトが起きないこと)を保証する、というのがRustの重要なイノベーションの1つです。

GCを避けることにより、Rustは数多くの利点を提供できます。リソースのクリーンアップが予測可能になり、メモリ管理のオーバーヘッドを減らすことができ、さらにランタイムシステムが実質的に不要になります。これらの特性によって、Rustは無駄が少なく、任意の文脈に埋め込むのが簡単になります。また、RustのコードとGCのある言語を連携させるのも非常に簡単になります。

Rustは所有権と借用の仕組みを通してGCを不要にしていますが、この仕組みは、一般的なリソース管理並行性などの、ほかの多くの問題にも役立ちます。

単一の所有権では不十分な場合には、RustプログラムはGCの代わりに、標準的なリファレンスカウントのスマートポインタ型であるRcや、スレッド安全版のArcを利用します。

しかし、我々は将来的な拡張として、オプショナルなガベージコレクションを研究しています。この目的は、SpidermonkeyV8 JavaScriptエンジンなどのようにガベージコレクションを持つランタイムと、スムーズな連携を可能にすることです。 最終的には、コンパイラサポートなしでpure Rustでのガベージコレクタを実装することを研究している人もいます。

私のプログラムが遅いのはなぜですか?

Rustコンパイラは、言われない限り最適化を行いません。最適化を行うとコンパイルが遅くなり、開発時には通常望ましくないためです

cargoでコンパイルを行う場合は、--releaseフラグを使ってください。rustcで直接コンパイルする場合は、-Oフラグを使ってください。いずれも最適化を有効にします。

Rustのコンパイルが遅いようです。なぜですか?

コードの翻訳と最適化のためです。Rustは高レベルの抽象化を提供し、それをコンパイルによって効率的な機械コードに落とします。この翻訳には時間がかかります。最適化を行う場合は特に。

しかしRustのコンパイル時間はそれほど悪くありませんし、今後改善していくと信じるに足る理由があります。C++とRustで同程度の規模のプロジェクトをコンパイルする場合、プロジェクト全体でのコンパイル時間は同程度であると考えられています。Rustのコンパイルが遅いと感じるのは、大部分が、C++とRustのコンパイルモデルの違いに起因します。C++のコンパイル単位はファイルですが、Rustのコンパイル単位は多くのファイルからなるクレートです。よって開発時にC++ファイルを1つ変更したときの再コンパイルは、Rustと比べると非常に少なくすみます。Rustコンパイラに段階的コンパイルを導入するためのリファクタリングに多くの努力が現在進行中です。これにより、RustはC++のコンパイルモデルと同等のコンパイル時間になるでしょう。

コンパイルモデルの他にも、コンパイルの性能に影響及ぼすような問題が、Rustの言語設計やコンパイラ実装に複数存在します。

第一に、Rustは少々複雑な型システムを持つので、Rustを実行時安全にするための制約を強制するのに無視できないコンパイル時間を費やしています。

第二に、Rustコンパイラは長年の技術的負債に悩まされています。特に、低品質なLLVM IRを出力するので、LLVMがこれを「修正」するのに時間を使います。未来のMIRベースの最適化と翻訳パスが、RustコンパイラがLLVMに課す負担を軽減するという希望があります。

第三に、Rustがコード生成にLLVMを使うことは諸刃の剣であるということです。LLVMのおかげでRustは天下一品の実行時性能を享受できる一方で、LLVMという大きなフレームワークはコンパイル時性能を重視していません。とりわけ、低品質な入力を処理するときの性能は考慮されていません。

最後に、Rustが好む(C++流の)単相的ジェネリクスは高速なコードを生成しますが、これは他の翻訳戦略と比べると非常に多くのコードを生成することに依っています。Rustプログラマはトレイトオブジェクトを使って、代わりに動的ディスパッチを用いることでコード爆発を避けることができます。

RustのHashMapが遅いのはなぜですか?

RustのHashMapはデフォルトでSipHashアルゴリズムを用います。これはハッシュテーブル衝突攻撃を防ぐように設計されており、また、さまざまな入力に対してそれなりの性能を提供するようになっています。

SipHashは多くの場合、他のアルゴリズムに引けを取らない性能を見せますが、整数のような短いキーに対しては著しく遅くなります。そういうわけで、RustプログラマはしばしばHashMapを使っているときに性能の低さが目につくこととなります。そのような場合にはよくFNVハッシャーが推奨されますが、SipHashのような衝突耐性はないことに注意してください。

統合されたベンチマーク基盤がないのはなぜですか?

あります。ただし、nightly release channelでのみ利用可能です。最終的には統合されたベンチマークのための機能拡張システムを構築することを計画していますが、いまのところ、現時点のシステムはunstableと考えられています

Rustは末尾呼び出し最適化を行いますか?

一般的には、いいえ。末尾呼び出し最適化は限られた状況では行われますが、保証はされていません。この機能は常に渇望されているので、Rustはキーワード(become)を予約していますが、技術的に可能かどうかも、実装されるかどうかも、はっきりしていません。ある文脈では末尾呼び出し除去を可能にする拡張が提案されていますが、現在のところ保留になっています。

Rustはランタイムを持ちますか?

Javaのような言語で使われる典型的な意味のランタイムは、持ちません。しかし、Rustの標準ライブラリの一部は、ヒープ、バックトレース、巻き戻し、スタックガードなどを提供する「ランタイム」であると考えられます。ユーザのmain関数を呼ぶ前に少しの初期化コードが実行されます。Rustの標準ライブラリはさらにCの標準ライブラリとリンクしますが、これはランタイムの初期化のようなことを行います。Rustコードは標準ライブラリなしでコンパイルできるので、この場合はランタイムはおおよそCのランタイムと等価です。

Syntax

Why curly braces? Why can't Rust's syntax be like Haskell's or Python's?

Use of curly braces to denote blocks is a common design choice in a variety of programming languages, and Rust’s consistency is useful for people already familiar with the style.

Curly braces also allow for more flexible syntax for the programmer and a simpler parser in the compiler.

I can leave out parentheses on if conditions, so why do I have to put brackets around single line blocks? Why is the C style not allowed?

Whereas C requires mandatory parentheses for if-statement conditionals but leaves brackets optional, Rust makes the opposite choice for its if-expressions. This keeps the conditional clearly separate from the body and avoids the hazard of optional brackets, which can lead to easy-to-miss errors during refactoring, like Apple’s goto fail bug.

Why is there no literal syntax for dictionaries?

Rust’s overall design preference is for limiting the size of the language while enabling powerful libraries. While Rust does provide initialization syntax for arrays and string literals, these are the only collection types built into the language. Other library-defined types, including the ubiquitous Vec collection type, use macros for initialization like the vec! macro.

This design choice of using Rust’s macro facilities to initialize collections will likely be extended generically to other collections in the future, enabling simple initialization of not only HashMap and Vec, but also other collection types such as BTreeMap. In the meantime, if you want a more convenient syntax for initializing collections, you can create your own macro to provide it.

When should I use an implicit return?

Rust is a very expression-oriented language, and “implicit returns” are part of that design. Constructs like ifs, matches, and normal blocks are all expressions in Rust. For example, the following code checks if an i64 is odd, returning the result by simply yielding it as a value:

fn is_odd(x: i64) -> bool {
    if x % 2 != 0 { true } else { false }
}

Although it can be simplified even further like so:

fn is_odd(x: i64) -> bool {
    x % 2 != 0
}

In each example, the last line of the function is the return value of that function. It is important to note that if a function ends in a semicolon, its return type will be (), indicating no returned value. Implicit returns must omit the semicolon to work.

Explicit returns are only used if an implicit return is impossible because you are returning before the end of the function’s body. While each of the above functions could have been written with a return keyword and semicolon, doing so would be unnecessarily verbose, and inconsistent with the conventions of Rust code.

Why aren't function signatures inferred?

In Rust, declarations tend to come with explicit types, while actual code has its types inferred. There are several reasons for this design:

Why does match have to be exhaustive?

To aid in refactoring and clarity.

First, if every possibility is covered by the match, adding variants to the enum in the future will cause a compilation failure, rather than an error at runtime. This type of compiler assistance makes fearless refactoring possible in Rust.

Second, exhaustive checking makes the semantics of the default case explicit: in general, the only safe way to have a non-exhaustive match would be to panic the thread if nothing is matched. Early versions of Rust did not require match cases to be exhaustive and it was found to be a great source of bugs.

It is easy to ignore all unspecified cases by using the _ wildcard:

match val.do_something() {
    Cat(a) => { /* ... */ }
    _      => { /* ... */ }
}

Numerics

Which of f32 and f64 should I prefer for floating-point math?

The choice of which to use is dependent on the purpose of the program.

If you are interested in the greatest degree of precision with your floating point numbers, then prefer f64. If you are more interested in keeping the size of the value small or being maximally efficient, and are not concerned about the associated inaccuracy of having fewer bits per value, then f32 is better. Operations on f32 are usually faster, even on 64-bit hardware. As a common example, graphics programming typically uses f32 because it requires high performance, and 32-bit floats are sufficient for representing pixels on the screen.

If in doubt, choose f64 for the greater precision.

Why can't I compare floats or use them as HashMap or BTreeMap keys?

Floats can be compared with the ==, !=, <, <=, >, and >= operators, and with the partial_cmp() function. == and != are part of the PartialEq trait, while <, <=, >, >=, and partial_cmp() are part of the PartialOrd trait.

Floats cannot be compared with the cmp() function, which is part of the Ord trait, as there is no total ordering for floats. Furthermore, there is no total equality relation for floats, and so they also do not implement the Eq trait.

There is no total ordering or equality on floats because the floating-point value NaN is not less than, greater than, or equal to any other floating-point value or itself.

Because floats do not implement Eq or Ord, they may not be used in types whose trait bounds require those traits, such as BTreeMap or HashMap. This is important because these types assume their keys provide a total ordering or total equality relation, and will malfunction otherwise.

There is a crate that wraps f32 and f64 to provide Ord and Eq implementations, which may be useful in certain cases.

How can I convert between numeric types?

There are two ways: the as keyword, which does simple casting for primitive types, and the Into and From traits, which are implemented for a number of type conversions (and which you can implement for your own types). The Into and From traits are only implemented in cases where conversions are lossless, so for example, f64::from(0f32) will compile while f32::from(0f64) will not. On the other hand, as will convert between any two primitive types, truncating values as necessary.

Why doesn't Rust have increment and decrement operators?

Preincrement and postincrement (and the decrement equivalents), while convenient, are also fairly complex. They require knowledge of evaluation order, and often lead to subtle bugs and undefined behavior in C and C++. x = x + 1 or x += 1 is only slightly longer, but unambiguous.

Strings

How can I convert a String or Vec<T> to a slice (&str and &[T])?

Usually, you can pass a reference to a String or Vec<T> wherever a slice is expected. Using Deref coercions, Strings and Vecs will automatically coerce to their respective slices when passed by reference with & or & mut.

Methods implemented on &str and &[T] can be accessed directly on String and Vec<T>. For example, some_string.char_at(0) will work even though char_at is a method on &str and some_string is a String.

In some cases, such as generic code, it’s necessary to convert manually. Manual conversions can be achieved using the slicing operator, like so: &my_vec[..].

How can I convert from &str to String or the other way around?

The to_string() method converts from a &str into a String, and Strings are automatically converted into &str when you borrow a reference to them. Both are demonstrated in the following example:

fn main() {
    let s = "Jane Doe".to_string();
    say_hello(&s);
}

fn say_hello(name: &str) {
    println!("Hello {}!", name);
}

What are the differences between the two different string types?

String is an owned buffer of UTF-8 bytes allocated on the heap. Mutable Strings can be modified, growing their capacity as needed. &str is a fixed-capacity “view” into a String allocated elsewhere, commonly on the heap, in the case of slices dereferenced from Strings, or in static memory, in the case of string literals.

&str is a primitive type implemented by the Rust language, while String is implemented in the standard library.

How do I do O(1) character access in a String?

You cannot. At least not without a firm understanding of what you mean by “character”, and preprocessing the string to find the index of the desired character.

Rust strings are UTF-8 encoded. A single visual character in UTF-8 is not necessarily a single byte as it would be in an ASCII-encoded string. Each byte is called a “code unit” (in UTF-16, code units are 2 bytes; in UTF-32 they are 4 bytes). “Code points” are composed of one or more code units, and combine in “grapheme clusters” which most closely approximate characters.

Thus, even though you may index on bytes in a UTF-8 string, you can’t access the ith code point or grapheme cluster in constant time. However, if you know at which byte that desired code point or grapheme cluster begins, then you can access it in constant time. Functions including str::find() and regex matches return byte indices, facilitating this sort of access.

Why are strings UTF-8 by default?

The str type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it’s best that the default treatment of I/O not involve having to recode codepoints in each direction.

This does mean that locating a particular Unicode codepoint inside a string is an O(n) operation, although if the starting byte index is already known then they can be accessed in O(1) as expected. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we’d like to point out a few important qualifications:

Scanning a str for ASCII-range codepoints can still be done safely byte-at-a-time. If you use .as_bytes(), pulling out a u8 costs only O(1) and produces a value that can be cast and compared to an ASCII-range char. So if you’re (say) line-breaking on '\n', byte-based treatment still works. UTF-8 was well-designed this way.

Most “character oriented” operations on text only work under very restricted language assumptions such as “ASCII-range codepoints only”. Outside ASCII-range, you tend to have to use a complex (non-constant-time) algorithm for determining linguistic-unit (glyph, word, paragraph) boundaries anyway. We recommend using an “honest” linguistically-aware, Unicode-approved algorithm.

The char type is UTF-32. If you are sure you need to do a codepoint-at-a-time algorithm, it’s trivial to write a type wstr = [char], and unpack a str into it in a single pass, then work with the wstr. In other words: the fact that the language is not “decoding to UTF32 by default” shouldn’t stop you from decoding (or re-encoding any other way) if you need to work with that encoding.

For a more in-depth explanation of why UTF-8 is usually preferable over UTF-16 or UTF-32, read the UTF-8 Everywhere manifesto.

What string type should I use?

Rust has four pairs of string types, each serving a distinct purpose. In each pair, there is an “owned” string type, and a “slice” string type. The organization looks like this:

  “Slice” type “Owned” type
UTF-8 str String
OS-compatible OsStr OsString
C-compatible CStr CString
System path Path PathBuf

Rust’s different string types serve different purposes. String and str are UTF-8 encoded general-purpose strings. OsString and OsStr are encoded according to the current platform, and are used when interacting with the operating system. CString and CStr are the Rust equivalent of strings in C, and are used in FFI code, and PathBuf and Path are convenience wrappers around OsString and OsStr, providing methods specific to path manipulation.

How can I write a function that accepts both &str and String?

There are several options, depending on the needs of the function:

Using Into<String>

In this example, the function will accept both owned strings and string slices, either doing nothing or converting the input into an owned string within the function body. Note that the conversion needs to be done explicitly, and will not happen otherwise.

fn accepts_both<S: Into<String>>(s: S) {
    let s = s.into();   // This will convert s into a `String`.
    // ... the rest of the function
}

Using AsRef<str>

In this example, the function will accept both owned strings and string slices, either doing nothing or converting the input into a string slice. This can be done automatically by taking the input by reference, like so:

fn accepts_both<S: AsRef<str>>(s: &S) {
    // ... the body of the function
}

Using Cow<str>

In this example, the function takes in a Cow<str>, which is not a generic type but a container, containing either an owned string or string slice as needed.

fn accepts_cow(s: Cow<str>) {
    // ... the body of the function
}

Collections

Can I implement data structures like vectors and linked lists efficiently in Rust?

If your reason for implementing these data structures is to use them for other programs, there’s no need, as efficient implementations of these data structures are provided by the standard library.

If, however, your reason is simply to learn, then you will likely need to dip into unsafe code. While these data structures can be implemented entirely in safe Rust, the performance is likely to be worse than it would be with the use of unsafe code. The simple reason for this is that data structures like vectors and linked lists rely on pointer and memory operations that are disallowed in safe Rust.

For example, a doubly-linked list requires that there be two mutable references to each node, but this violates Rust’s mutable reference aliasing rules. You can solve this using Weak<T>, but the performance will be poorer than you likely want. With unsafe code you can bypass the mutable reference aliasing rule restriction, but must manually verify that your code introduces no memory safety violations.

How can I iterate over a collection without moving/consuming it?

The easiest way is by using the collection’s IntoIterator implementation. Here is an example for &Vec:

let v = vec![1,2,3,4,5];
for item in &v {
    print!("{} ", item);
}
println!("\nLength: {}", v.len());

Rust for loops call into_iter() (defined on the IntoIterator trait) for whatever they’re iterating over. Anything implementing the IntoIterator trait may be looped over with a for loop. IntoIterator is implemented for &Vec and &mut Vec, causing the iterator from into_iter() to borrow the contents of the collection, rather than moving/consuming them. The same is true for other standard collections as well.

If a moving/consuming iterator is desired, write the for loop without & or &mut in the iteration.

If you need direct access to a borrowing iterator, you can usually get it by calling the iter() method.

Why do I need to type the array size in the array declaration?

You don’t necessarily have to. If you’re declaring an array directly, the size is inferred based on the number of elements. But if you’re declaring a function that takes a fixed-size array, the compiler has to know how big that array will be.

One thing to note is that currently Rust doesn’t offer generics over arrays of different size. If you’d like to accept a contiguous container of a variable number of values, use a Vec or slice (depending on whether you need ownership).

Ownership

How can I implement a graph or other data structure that contains cycles?

There are at least four options (discussed at length in Too Many Linked Lists):

How can I define a struct that contains a reference to one of its own fields?

It’s possible, but useless to do so. The struct becomes permanently borrowed by itself and therefore can’t be moved. Here is some code illustrating this:

use std::cell::Cell;

#[derive(Debug)]
struct Unmovable<'a> {
    x: u32,
    y: Cell<Option<&'a u32>>,
}


fn main() {
    let test = Unmovable { x: 42, y: Cell::new(None) };
    test.y.set(Some(&test.x));

    println!("{:?}", test);
}

What is the difference between passing by value, consuming, moving, and transferring ownership?

These are different terms for the same thing. In all cases, it means the value has been moved to another owner, and moved out of the possession of the original owner, who can no longer use it. If a type implements the Copy trait, the original owner’s value won’t be invalidated, and can still be used.

Why can values of some types be used after passing them to a function, while reuse of values of other types results in an error?

If a type implements the Copy trait, then it will be copied when passed to a function. All numeric types in Rust implement Copy, but struct types do not implement Copy by default, so they are moved instead. This means that the struct can no longer be used elsewhere, unless it is moved back out of the function via the return.

How do you deal with a "use of moved value" error?

This error means that the value you’re trying to use has been moved to a new owner. The first thing to check is whether the move in question was necessary: if it moved into a function, it may be possible to rewrite the function to use a reference, rather than moving. Otherwise if the type being moved implements Clone, then calling clone() on it before moving will move a copy of it, leaving the original still available for further use. Note though that cloning a value should typically be the last resort since cloning can be expensive, causing further allocations.

If the moved value is of your own custom type, consider implementing Copy (for implicit copying, rather than moving) or Clone (explicit copying). Copy is most commonly implemented with #[derive(Copy, Clone)] (Copy requires Clone), and Clone with #[derive(Clone)].

If none of these are possible, you may want to modify the function that acquired ownership to return ownership of the value when the function exits.

What are the rules for using self, &self, or &mut self in a method declaration?

How can I understand the borrow checker?

The borrow checker applies only a few rules, which can be found in the Rust book’s section on borrowing, when evaluating Rust code. These rules are:

First, any borrow must last for a scope no greater than that of the owner. Second, you may have one or the other of these two kinds of borrows, but not both at the same time:

  • one or more references (&T) to a resource.
  • exactly one mutable reference (&mut T)

While the rules themselves are simple, following them consistently is not, particularly for those unaccustomed to reasoning about lifetimes and ownership.

The first step in understanding the borrow checker is reading the errors it produces. A lot of work has been put into making sure the borrow checker provides quality assistance in resolving the issues it identifies. When you encounter a borrow checker problem, the first step is to slowly and carefully read the error reported, and to only approach the code after you understand the error being described.

The second step is to become familiar with the ownership and mutability-related container types provided by the Rust standard library, including Cell, RefCell, and Cow. These are useful and necessary tools for expressing certain ownership and mutability situations, and have been written to be of minimal performance cost.

The single most important part of understanding the borrow checker is practice. Rust’s strong static analyses guarantees are strict and quite different from what many programmers have worked with before. It will take some time to become completely comfortable with everything.

If you find yourself struggling with the borrow checker, or running out of patience, always feel free to reach out to the Rust community for help.

When is Rc useful?

This is covered in the official documentation for Rc, Rust’s non-atomically reference-counted pointer type. In short, Rc and its thread-safe cousin Arc are useful to express shared ownership, and have the system automatically deallocate the associated memory when no one has access to it.

How do I return a closure from a function?

To return a closure from a function, it must be a “move closure”, meaning that the closure is declared with the move keyword. As explained in the Rust book, this gives the closure its own copy of the captured variables, independent of its parent stack frame. Otherwise, returning a closure would be unsafe, as it would allow access to variables that are no longer valid; put another way: it would allow reading potentially invalid memory. The closure must also be wrapped in a Box, so that it is allocated on the heap. Read more about this in the book.

What is a deref coercion and how does it work?

A deref coercion is a handy coercion that automatically converts references to pointers (e.g., &Rc<T> or &Box<T>) into references to their contents (e.g., &T). Deref coercions exist to make using Rust more ergonomic, and are implemented via the Deref trait.

A Deref implementation indicates that the implementing type may be converted into a target by a call to the deref method, which takes an immutable reference to the calling type and returns a reference (of the same lifetime) to the target type. The * prefix operator is shorthand for the deref method.

They’re called “coercions” because of the following rule, quoted here from the Rust book:

If you have a type U, and it implements Deref<Target=T>, values of &U will automatically coerce to a &T.

For example, if you have a &Rc<String>, it will coerce via this rule into a &String, which then coerces to a &str in the same way. So if a function takes a &str parameter, you can pass in a &Rc<String> directly, with all coercions handled automatically via the Deref trait.

The most common sorts of deref coercions are:

Lifetimes

Why lifetimes?

Lifetimes are Rust’s answer to the question of memory safety. They allow Rust to ensure memory safety without the performance costs of garbage collection. They are based on a variety of academic work, which can be found in the Rust book.

Why is the lifetime syntax the way it is?

The 'a syntax comes from the ML family of programming languages, where 'a is used to indicate a generic type parameter. For Rust, the syntax had to be something that was unambiguous, noticeable, and fit nicely in a type declaration right alongside traits and references. Alternative syntaxes have been discussed, but no alternative syntax has been demonstrated to be clearly better.

How do I return a borrow to something I created from a function?

You need to ensure that the borrowed item will outlive the function. This can be done by binding the output lifetime to some input lifetime like so:

type Pool = TypedArena<Thing>;

// (the lifetime below is only written explicitly for
// expository purposes; it can be omitted via the
// elision rules described in a later FAQ entry)
fn create_borrowed<'a>(pool: &'a Pool,
                       x: i32,
                       y: i32) -> &'a Thing {
    pool.alloc(Thing { x: x, y: y })
}

An alternative is to eliminate the references entirely by returning an owning type like String:

fn happy_birthday(name: &str, age: i64) -> String {
    format!("Hello {}! You're {} years old!", name, age)
}

This approach is simpler, but often results in unnecessary allocations.

Why do some references have lifetimes, like &'a T, and some do not, like &T?

In fact, all reference types have a lifetime, but most of the time you do not have to write it explicitly. The rules are as follows:

  1. Within a function body, you never have to write a lifetime explicitly; the correct value should always be inferred.
  2. Within a function signature (for example, in the types of its arguments, or its return type), you may have to write a lifetime explicitly. Lifetimes there use a simple defaulting scheme called “lifetime elision”, which consists of the following three rules:
    • Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter.
    • If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function.
    • If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
  3. Finally, in a struct or enum definition, all lifetimes must be explicitly declared.

If these rules result in compilation errors, the Rust compiler will provide an error message indicating the error caused, and suggesting a potential solution based on which step of the inference process caused the error.

How can Rust guarantee "no null pointers" and "no dangling pointers"?

The only way to construct a value of type &Foo or &mut Foo is to specify an existing value of type Foo that the reference points to. The reference “borrows” the original value for a given region of code (the lifetime of the reference), and the value being borrowed from cannot be moved or destroyed for the duration of the borrow.

How do I express the absence of a value without null?

You can do that with the Option type, which can either be Some(T) or None. Some(T) indicates that a value of type T is contained within, while None indicates the absence of a value.

Generics

What is "monomorphisation"?

Monomorphisation specializes each use of a generic function (or structure) with specific instance, based on the parameter types of calls to that function (or uses of the structure).

During monomorphisation a new copy of the generic function is translated for each unique set of types the function is instantiated with. This is the same strategy used by C++. It results in fast code that is specialized for every call-site and statically dispatched, with the tradeoff that functions instantiated with many different types can cause “code bloat”, where multiple function instances result in larger binaries than would be created with other translation strategies.

Functions that accept trait objects instead of type parameters do not undergo monomorphisation. Instead, methods on the trait objects are dispatched dynamically at runtime.

What's the difference between a function and a closure that doesn't capture any variables?

Functions and closures are operationally equivalent, but have different runtime representations due to their differing implementations.

Functions are a built-in primitive of the language, while closures are essentially syntactic sugar for one of three traits: Fn, FnMut, and FnOnce. When you make a closure, the Rust compiler automatically creates a struct implementing the appropriate trait of those three and containing the captured environment variables as members, and makes it so the struct can be called as a function. Bare functions can not capture an environment.

The big difference between these traits is how they take the self parameter. Fn takes &self, FnMut takes &mut self, and FnOnce takes self.

Even if a closure does not capture any environment variables, it is represented at runtime as two pointers, the same as any other closure.

What are higher-kinded types, why would I want them, and why doesn't Rust have them?

Higher-kinded types are types with unfilled parameters. Type constructors, like Vec, Result, and HashMap are all examples of higher-kinded types: each requires some additional type parameters in order to actually denote a specific type, like Vec<u32>. Support for higher-kinded types means these “incomplete” types may be used anywhere “complete” types can be used, including as generics for functions.

Any complete type, like i32, bool, or char is of kind * (this notation comes from the field of type theory). A type with one parameter, like Vec<T> is of kind * -> *, meaning that Vec<T> takes in a complete type like i32 and returns a complete type Vec<i32>. A type with three parameters, like HashMap<K, V, S> is of kind * -> * -> * -> *, and takes in three complete types (like i32, String, and RandomState) to produce a new complete type HashMap<i32, String, RandomState>.

In addition to these examples, type constructors can take lifetime arguments, which we’ll denote as Lt. For example, slice::Iter has kind Lt -> * -> *, because it must be instantiated like Iter<'a, u32>.

The lack of support for higher-kinded types makes it difficult to write certain kinds of generic code. It’s particularly problematic for abstracting over concepts like iterators, since iterators are often parameterized over a lifetime at least. That in turn has prevented the creation of traits abstracting over Rust’s collections.

Another common example is concepts like functors or monads, both of which are type constructors, rather than single types.

Rust doesn’t currently have support for higher-kinded types because it hasn’t been a priority compared to other improvements we want to make. Since the design is a major, cross-cutting change, we also want to approach it carefully. But there’s no inherent reason for the current lack of support.

What do named type parameters like <T=Foo> in generic types mean?

These are called associated types, and they allow for the expression of trait bounds that can’t be expressed with a where clause. For example, a generic bound X: Bar<T=Foo> means “X must implement the trait Bar, and in that implementation of Bar, X must choose Foo for Bar’s associated type, T.” Examples of where such a constraint cannot be expressed via a where clause include trait objects like Box<Bar<T=Foo>>.

Associated types exist because generics often involve families of types, where one type determines all of the others in a family. For example, a trait for graphs might have as its Self type the graph itself, and have associated types for nodes and for edges. Each graph type uniquely determines the associated types. Using associated types makes it much more concise to work with these families of types, and also provides better type inference in many cases.

Can I overload operators? Which ones and how?

You can provide custom implementations for a variety of operators using their associated traits: Add for +, Mul for *, and so on. It looks like this:

use std::ops::Add;

struct Foo;

impl Add for Foo {
    type Output = Foo;
    fn add(self, rhs: Foo) -> Self::Output {
        println!("Adding!");
        self
    }
}

The following operators can be overloaded:

Operation Trait
+ Add
+= AddAssign
binary - Sub
-= SubAssign
* Mul
*= MulAssign
/ Div
/= DivAssign
unary - Neg
% Rem
%= RemAssign
& BitAnd
| BitOr
|= BitOrAssign
^ BitXor
^= BitXorAssign
! Not
<< Shl
<<= ShlAssign
>> Shr
>>= ShrAssign
* Deref
mut * DerefMut
[] Index
mut [] IndexMut

Why the split between Eq/PartialEq and Ord/PartialOrd?

There are some types in Rust whose values are only partially ordered, or have only partial equality. Partial ordering means that there may be values of the given type that are neither less than nor greater than each other. Partial equality means that there may be values of the given type that are not equal to themselves.

Floating point types (f32 and f64) are good examples of each. Any floating point type may have the value NaN (meaning “not a number”). NaN is not equal to itself (NaN == NaN is false), and not less than or greater than any other floating point value. As such, both f32 and f64 implement PartialOrd and PartialEq but not Ord and not Eq.

As explained in the earlier question on floats, these distinctions are important because some collections rely on total orderings/equality in order to give correct results.

Input / Output

How do I read a file into a String?

Using the read_to_string() method, which is defined on the Read trait in std::io.

use std::io::Read;
use std::fs::File;

fn read_file(path: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(path));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));  // `s` contains the contents of "foo.txt"
    Ok(s)
}

fn main() {
    match read_file("foo.txt") {
        Ok(_) => println!("Got file contents!"),
        Err(err) => println!("Getting file contents failed with error: {}", err)
    };
}

How do I read file input efficiently?

The File type implements the Read trait, which has a variety of functions for reading and writing data, including read(), read_to_end(), bytes(), chars(), and take(). Each of these functions reads a certain amount of input from a given file. read() reads as much input as the underlying system will provide in a single call. read_to_end() reads the entire buffer into a vector, allocating as much space as is needed. bytes() and chars() allow you to iterate over the bytes and characters of the file, respectively. Finally, take() allows you to read up to an arbitrary number of bytes from the file. Collectively, these should allow you to efficiently read in any data you need.

For buffered reads, use the BufReader struct, which helps to reduce the number of system calls when reading.

How do I do asynchronous input / output in Rust?

There are several libraries providing asynchronous input / output in Rust, including mioco, coio-rs, and rotor.

How do I get command line arguments in Rust?

The easiest way is to use Args, which provides an iterator over the input arguments.

If you’re looking for something more powerful, there are a number of options on crates.io.

Error Handling

Why doesn't Rust have exceptions?

Exceptions complicate understanding of control-flow, they express validity/invalidity outside of the type system, and they interoperate poorly with multithreaded code (a major focus of Rust).

Rust prefers a type-based approach to error handling, which is covered at length in the book. This fits more nicely with Rust’s control flow, concurrency, and everything else.

What's the deal with unwrap() everywhere?

unwrap() is a function that extracts the value inside an Option or Result and panics if no value is present.

unwrap() shouldn’t be your default way to handle errors you expect to arise, such as incorrect user input. In production code, it should be treated like an assertion that the value is non-empty, which will crash the program if violated.

It’s also useful for quick prototypes where you don’t want to handle an error yet, or blog posts where error handling would distract from the main point.

Why do I get an error when I try to run example code that uses the try! macro?

It’s probably an issue with the function’s return type. The try! macro either extracts the value from a Result, or returns early with the error Result is carrying. This means that try only works for functions that return Result themselves, where the Err-constructed type implements From::from(err). In particular, this means that the try! macro cannot work inside the main function.

Is there an easier way to do error handling than having Results everywhere?

If you’re looking for a way to avoid handling Results in other people’s code, there’s always unwrap(), but it’s probably not what you want. Result is an indicator that some computation may or may not complete successfully. Requiring you to handle these failures explicitly is one of the ways that Rust encourages robustness. Rust provides tools like the try! macro to make handling failures ergonomic.

If you really don’t want to handle an error, use unwrap(), but know that doing so means that the code panics on failure, which usually results in a shutting down the process.

Concurrency

Can I use static values across threads without an unsafe block?

Mutation is safe if it’s synchronized. Mutating a static Mutex (lazily initialized via the lazy-static crate) does not require an unsafe block, nor does mutating a static AtomicUsize (which can be initialized without lazy_static).

More generally, if a type implements Sync and does not implement Drop, it can be used in a static.

Macros

Can I write a macro to generate identifiers?

Not currently. Rust macros are “hygienic macros”, which intentionally avoid capturing or creating identifiers that may cause unexpected collisions with other identifiers. Their capabilities are significantly different than the style of macros commonly associated with the C preprocessor. Macro invocations can only appear in places where they are explicitly supported: items, method declarations, statements, expressions, and patterns. Here, “method declarations” means a blank space where a method can be put. They can’t be used to complete a partial method declaration. By the same logic, they can’t be used to complete a partial variable declaration.

Debugging and Tooling

How do I debug Rust programs?

Rust programs can be debugged using gdb or lldb, the same as C and C++. In fact, every Rust installation comes with one or both of rust-gdb and rust-lldb (depending on platform support). These are wrappers over gdb and lldb with Rust pretty-printing enabled.

rustc said a panic occurred in standard library code. How do I locate the mistake in my code?

This error is usually caused by unwrap()ing a None or Err in client code. Enabling backtraces by setting the environment variable RUST_BACKTRACE=1 helps with getting more information. Compiling in debug mode (the default for cargo build) is also helpful. Using a debugger like the provided rust-gdb or rust-lldb is also helpful.

What IDE should I use?

There are a number of options for development environment with Rust, all of which are detailed on the official IDE support page.

gofmt is great. Where's rustfmt?

rustfmt is right here, and is being actively developed to make reading Rust code as easy and predictable as possible.

Low-Level

How do I memcpy bytes?

If you want to clone an existing slice safely, you can use clone_from_slice.

To copy potentially overlapping bytes, use copy. To copy nonoverlapping bytes, use copy_nonoverlapping. Both of these functions are unsafe, as both can be used to subvert the language’s safety guarantees. Take care when using them.

Can Rust function reasonably without the standard library?

Absolutely. Rust programs can be set to not load the standard library using the #![no_std] attribute. With this attribute set, you can continue to use the Rust core library, which is nothing but the platform-agnostic primitives. As such, it doesn’t include IO, concurrency, heap allocation, etc.

Can I write an operating system in Rust?

Yes! In fact there are several projects underway doing just that.

How can I read or write numeric types like i32 or f64 in big-endian or little-endian format in a file or other byte stream?

You should check out the byteorder crate, which provides utilities for exactly that.

Does Rust guarantee a specific data layout?

Not by default. In the general case, enum and struct layouts are undefined. This allows the compiler to potentially do optimizations like re-using padding for the discriminant, compacting variants of nested enums, reordering fields to remove padding, etc. enums which carry no data (“C-like”) are eligible to have a defined representation. Such enums are easily distinguished in that they are simply a list of names that carry no data:

enum CLike {
    A,
    B = 32,
    C = 34,
    D
}

The #[repr(C)] attribute can be applied to such enums to give them the same representation they would have in equivalent C code. This allows using Rust enums in FFI code where C enums are also used, for most use cases. The attribute can also be applied to structs to get the same layout as a C struct would.

Cross-Platform

What's the idiomatic way to express platform-specific behavior in Rust?

Platform-specific behavior can be expressed using conditional compilation attributes such as target_os, target_family, target_endian, etc.

Can Rust be used for Android/iOS programming?

Yes it can! There are already examples of using Rust for both Android and iOS. It does require a bit of work to set up, but Rust functions fine on both platforms.

Can I run my Rust program in a web browser?

Not yet, but there are efforts underway to make Rust compile to the web with Emscripten.

How do I cross-compile in Rust?

Cross compilation is possible in Rust, but it requires a bit of work to set up. Every Rust compiler is a cross-compiler, but libraries need to be cross-compiled for the target platform.

Rust does distribute copies of the standard library for each of the supported platforms, which are contained in the rust-std-* files for each of the build directories found on the distribution page, but there are not yet automated ways to install them.

Modules and Crates

What is the relationship between a module and a crate?

Why can't the Rust compiler find this library I'm useing?

There are a number of possible answers, but a common mistake is not realizing that use declarations are relative to the crate root. Try rewriting your declarations to use the paths they would use if defined in the root file of your project and see if that fixes the problem.

There are also self and super, which disambiguate use paths as being relative to the current module or parent module, respectively.

For complete information on useing libraries, read the Rust book’s chapter “Crates and Modules”.

Why do I have to declare module files with mod at the top level of the crate, instead of just useing them?

There are two ways to declare modules in Rust, inline or in another file. Here is an example of each:

// In main.rs
mod hello {
    pub fn f() {
        println!("hello!");
    }
}

fn main() {
    hello::f();
}
// In main.rs
mod hello;

fn main() {
    hello::f();
}

// In hello.rs
pub fn f() {
    println!("hello!");
}

In the first example, the module is defined in the same file it’s used. In the second example, the module declaration in the main file tells the compiler to look for either hello.rs or hello/mod.rs, and to load that file.

Note the difference between mod and use: mod declares that a module exists, whereas use references a module declared elsewhere, bringing its contents into scope within the current module.

How do I configure Cargo to use a proxy?

As explained on the Cargo configuration documentation, you can set Cargo to use a proxy by setting the “proxy” variable under [http] in the configuration file.

Why can't the compiler find the method implementation even though I'm already useing the crate?

For methods defined on a trait, you have to explicitly import the trait declaration. This means it’s not enough to import a module where a struct implements the trait, you must also import the trait itself.

Why can't the compiler infer use declarations for me?

It probably could, but you also don’t want it to. While in many cases it is likely that the compiler could determine the correct module to import by simply looking for where a given identifier is defined, this may not be the case in general. Any decision rule in rustc for choosing between competing options would likely cause surprise and confusion in some cases, and Rust prefers to be explicit about where names are coming from.

For example, the compiler could say that in the case of competing identifier definitions the definition from the earliest imported module is chosen. So if both module foo and module bar define the identifier baz, but foo is the first registered module, the compiler would insert use foo::baz;.

mod foo;
mod bar;

// use foo::baz  // to be inserted by the compiler.

fn main() {
  baz();
}

If you know this is going to happen, perhaps it saves a small number of keystrokes, but it also greatly increases the possibility for surprising error messages when you actually meant for baz() to be bar::baz(), and it decreases the readability of the code by making the meaning of a function call dependent on module declaration. These are not tradeoffs we are willing to make.

However, in the future, an IDE could help manage declarations, which gives you the best of both worlds: machine assistance for pulling in names, but explicit declarations about where those names are coming from.

How do I do dynamic Rust library loading?

Import dynamic libraries in Rust with libloading, which provides a cross-platform system for dynamic linking.

Why doesn't crates.io have namespaces?

Quoting the official explanation of https://crates.io’s design:

In the first month with crates.io, a number of people have asked us about the possibility of introducing namespaced packages.

While namespaced packages allow multiple authors to use a single, generic name, they add complexity to how packages are referenced in Rust code and in human communication about packages. At first glance, they allow multiple authors to claim names like http, but that simply means that people will need to refer to those packages as wycats' http or reem's http, offering little benefit over package names like wycats-http or reem-http.

When we looked at package ecosystems without namespacing, we found that people tended to go with more creative names (like nokogiri instead of “tenderlove’s libxml2”). These creative names tend to be short and memorable, in part because of the lack of any hierarchy. They make it easier to communicate concisely and unambiguously about packages. They create exciting brands. And we’ve seen the success of several 10,000+ package ecosystems like NPM and RubyGems whose communities are prospering within a single namespace.

In short, we don’t think the Cargo ecosystem would be better off if Piston chose a name like bvssvni/game-engine (allowing other users to choose wycats/game-engine) instead of simply piston.

Because namespaces are strictly more complicated in a number of ways, and because they can be added compatibly in the future should they become necessary, we’re going to stick with a single shared namespace.

Libraries

How can I make an HTTP request?

The standard library does not include an implementation of HTTP, so you will want to use an external crate. Hyper is the most popular, but there are a number of others as well.

How can I write a GUI application in Rust?

There are a variety of ways to write GUI applications in Rust. Just check out this list of GUI frameworks.

How can I parse JSON/XML?

Serde is the recommended library for serialization and deserialization of Rust data to and from a number of different formats.

Is there a standard 2D+ vector and shape crate?

Not yet! Want to write one?

How do I write an OpenGL app in Rust?

Glium is the major library for OpenGL programming in Rust. GLFW is also a solid option.

Can I write a video game in Rust?

Yes you can! The major game programming library for Rust is Piston, and there’s both a subreddit for game programming in Rust and an IRC channel (#rust-gamedev on Mozilla IRC) as well.

Design Patterns

Is Rust object oriented?

It is multi-paradigm. Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you’re accustomed to.

How do I map object-oriented concepts to Rust?

That depends. There are ways of translating object-oriented concepts like multiple inheritance to Rust, but as Rust is not object-oriented the result of the translation may look substantially different from its appearance in an OO language.

How do I handle configuration of a struct with optional parameters?

The easiest way is to use the Option type in whatever function you’re using to construct instances of the struct (usually new()). Another way is to use the builder pattern, where only certain functions instantiating member variables must be called before the construction of the built type.

How do I do global variables in Rust?

Globals in Rust can be done using const declarations for compile-time computed global constants, while static can be used for mutable globals. Note that modifying a static mut variable requires the use of unsafe, as it allows for data races, one of the things guaranteed not to happen in safe Rust. One important distinction between const and static values is that you can take references to static values, but not references to const values, which don’t have a specified memory location. For more information on const vs. static, read the Rust book.

How can I set compile-time constants that are defined procedurally?

Rust currently has limited support for compile time constants. You can define primitives using const declarations (similar to static, but immutable and without a specified location in memory) as well as define const functions and inherent methods.

To define procedural constants that can’t be defined via these mechanisms, use the lazy-static crate, which emulates compile-time evaluation by automatically evaluating the constant at first use.

Can I run initialization code that happens before main?

Rust has no concept of “life before main”. The closest you’ll see can be done through the lazy-static crate, which simulates a “before main” by lazily initializing static variables at their first usage.

Does Rust allow non-constant-expression values for globals?

No. Globals cannot have a non-constant-expression constructor and cannot have a destructor at all. Static constructors are undesirable because portably ensuring a static initialization order is difficult. Life before main is often considered a misfeature, so Rust does not allow it.

See the C++ FQA about the “static initialization order fiasco”, and Eric Lippert’s blog for the challenges in C#, which also has this feature.

You can approximate non-constant-expression globals with the lazy-static crate.

Other Languages

How can I implement something like C's struct X { static int X; }; in Rust?

Rust does not have static fields as shown in the code snippet above. Instead, you can declare a static variable in a given module, which is kept private to that module.

How can I convert a C-style enum to an integer, or vice-versa?

Converting a C-style enum to an integer can be done with an as expression, like e as i64 (where e is some enum).

Converting in the other direction can be done with a match statement, which maps different numeric values to different potential values for the enum.

Why do Rust programs have larger binary sizes than C programs?

There are several factors that contribute to Rust programs having, by default, larger binary sizes than functionally-equivalent C programs. In general, Rust’s preference is to optimize for the performance of real-world programs, not the size of small programs.

Monomorphization

Rust monomorphizes generics, meaning that a new version of a generic function or type is generated for each concrete type it’s used with in the program. This is similar to how templates work in C++. For example, in the following program:

fn foo<T>(t: T) {
    // ... do something
}

fn main() {
    foo(10);       // i32
    foo("hello");  // &str
}

Two distinct versions of foo will be in the final binary, one specialized to an i32 input, one specialized to a &str input. This enables efficient static dispatch of the generic function, but at the cost of a larger binary.

Debug symbols

Rust programs compile with some debug symbols retained, even when compiling in release mode. These are used for providing backtraces on panics, and can be removed with strip, or another debug symbol removal tool. It is also useful to note that compiling in release mode with Cargo is equivalent to setting optimization level 3 with rustc. An alternative optimization level (called s or z) has recently landed and tells the compiler to optimize for size rather than performance.

Jemalloc

Rust uses jemalloc as the default allocator, which adds some size to compiled Rust binaries. Jemalloc is chosen because it is a consistent, quality allocator that has preferable performance characteristics compared to a number of common system-provided allocators. There is work being done to make it easier to use custom allocators, but that work is not yet finished.

Link-time optimization

Rust does not do link-time optimization by default, but can be instructed to do so. This increases the amount of optimization that the Rust compiler can potentially do, and can have a small effect on binary size. This effect is likely larger in combination with the previously mentioned size optimizing mode.

Standard library

The Rust standard library includes libbacktrace and libunwind, which may be undesirable in some programs. Using #![no_std] can thus result in smaller binaries, but will also usually result in substantial changes to the sort of Rust code you’re writing. Note that using Rust without the standard library is often functionally closer to the equivalent C code.

As an example, the following C program reads in a name and says “hello” to the person with that name.

#include <stdio.h>

int main(void) {
    printf("What's your name?\n");
    char input[100] = {0};
    scanf("%s", input);
    printf("Hello %s!\n", input);
    return 0;
}

Rewriting this in Rust, you may get something like the following:

use std::io;

fn main() {
    println!("What's your name?");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    println!("Hello {}!", input);
}

This program, when compiled and compared against the C program, will have a larger binary and use more memory. But this program is not exactly equivalent to the above C code. The equivalent Rust code would instead look something like this:

#![feature(lang_items)]
#![feature(libc)]
#![feature(no_std)]
#![feature(start)]
#![no_std]

extern crate libc;

extern "C" {
    fn printf(fmt: *const u8, ...) -> i32;
    fn scanf(fmt: *const u8, ...) -> i32;
}

#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    unsafe {
        printf(b"What's your name?\n\0".as_ptr());
        let mut input = [0u8; 100];
        scanf(b"%s\0".as_ptr(), &mut input);
        printf(b"Hello %s!\n\0".as_ptr(), &input);
        0
    }
}

#[lang="eh_personality"] extern fn eh_personality() {}
#[lang="panic_fmt"] fn panic_fmt() -> ! { loop {} }
#[lang="stack_exhausted"] extern fn stack_exhausted() {}

Which should indeed roughly match C in memory usage, at the expense of more programmer complexity, and a lack of static guarantees usually provided by Rust (avoided here with the use of unsafe).

Why does Rust not have a stable ABI like C does, and why do I have to annotate things with extern?

Committing to an ABI is a big decision that can limit potentially advantageous language changes in the future. Given that Rust only hit 1.0 in May of 2015, it is still too early to make a commitment as big as a stable ABI. This does not mean that one won’t happen in the future, though. (Though C++ has managed to go for many years without specifying a stable ABI.)

The extern keyword allows Rust to use specific ABI’s, such as the well-defined C ABI, for interop with other languages.

Can Rust code call C code?

Yes. Calling C code from Rust is designed to be as efficient as calling C code from C++.

Can C code call Rust code?

Yes. The Rust code has to be exposed via an extern declaration, which makes it C-ABI compatible. Such a function can be passed to C code as a function pointer or, if given the #[no_mangle] attribute to disable symbol mangling, can be called directly from C code.

I already write perfect C++. What does Rust give me?

Modern C++ includes many features that make writing safe and correct code less error-prone, but it’s not perfect, and it’s still easy to introduce unsafety. This is something the C++ core developers are working to overcome, but C++ is limited by a long history that predates a lot of the ideas they are now trying to implement.

Rust was designed from day one to be a safe systems programming language, which means it’s not limited by historic design decisions that make getting safety right in C++ so complicated. In C++, safety is achieved by careful personal discipline, and is very easy to get wrong. In Rust, safety is the default. It gives you the ability to work in a team that includes people less perfect than you are, without having to spend your time double-checking their code for safety bugs.

How do I do the equivalent of C++ template specialization in Rust?

Rust doesn’t currently have an exact equivalent to template specialization, but it is being worked on and will hopefully be added soon. However, similar effects can be achieved via associated types.

How does Rust's ownership system relate to move semantics in C++?

The underlying concepts are similar, but the two systems work very differently in practice. In both systems, “moving” a value is a way to transfer ownership of its underlying resources. For example, moving a string would transfer the string’s buffer rather than copying it.

In Rust, ownership transfer is the default behavior. For example, if I write a function that takes a String as argument, this function will take ownership of the String value supplied by its caller:

fn process(s: String) { }

fn caller() {
    let s = String::from("Hello, world!");
    process(s); // Transfers ownership of `s` to `process`
    process(s); // Error! ownership already transferred.
}

As you can see in the snippet above, in the function caller, the first call to process transfers ownership of the variable s. The compiler tracks ownership, so the second call to process results in an error, because it is illegal to give away ownership of the same value twice. Rust will also prevent you from moving a value if there is an outstanding reference into that value.

C++ takes a different approach. In C++, the default is to copy a value (to invoke the copy constructor, more specifically). However, callees can declare their arguments using an “rvalue reference”, like string&&, to indicate that they will take ownership of some of the resources owned by that argument (in this case, the string’s internal buffer). The caller then must either pass a temporary expression or make an explicit move using std::move. The rough equivalent to the function process above, then, would be:

void process(string&& s) { }

void caller() {
    string s("Hello, world!");
    process(std::move(s));
    process(std::move(s));
}

C++ compilers are not obligated to track moves. For example, the code above compiles without a warning or error, at least using the default settings on clang. Moreover, in C++ ownership of the string s itself (if not its internal buffer) remains with caller, and so the destructor for s will run when caller returns, even though it has been moved (in Rust, in contrast, moved values are dropped only by their new owners).

How can I interoperate with C++ from Rust, or with Rust from C++?

Rust and C++ can interoperate through C. Both Rust and C++ provide a foreign function interface for C, and can use that to communicate between each other. If writing C bindings is too tedious, you can always use rust-bindgen to help automatically generate workable C bindings.

Does Rust have C++-style constructors?

No. Functions serve the same purpose as constructors without adding language complexity. The usual name for the constructor-equivalent function in Rust is new(), although this is just a convention rather than a language rule. The new() function in fact is just like any other function. An example of it looks like so:

struct Foo {
    a: i32,
    b: f64,
    c: bool,
}

impl Foo {
    fn new() -> Foo {
        Foo {
            a: 0,
            b: 0.0,
            c: false,
        }
    }
}

Does Rust have copy constructors?

Not exactly. Types which implement Copy will do a standard C-like “shallow copy” with no extra work (similar to trivially copyable types in C++). It is impossible to implement Copy types that require custom copy behavior. Instead, in Rust “copy constructors” are created by implementing the Clone trait, and explicitly calling the clone method. Making user-defined copy operators explicit surfaces the underlying complexity, making it easier for the developer to identify potentially expensive operations.

Does Rust have move constructors?

No. Values of all types are moved via memcpy. This makes writing generic unsafe code much simpler since assignment, passing and returning are known to never have a side effect like unwinding.

How are Go and Rust similar, and how are they different?

Rust and Go have substantially different design goals. The following differences are not the only ones (which are too numerous to list), but are a few of the more important ones:

How do Rust traits compare to Haskell typeclasses?

Rust traits are similar to Haskell typeclasses, but are currently not as powerful, as Rust cannot express higher-kinded types. Rust’s associated types are equivalent to Haskell type families.

Some specific difference between Haskell typeclasses and Rust traits include:

Documentation

Why are so many Rust answers on Stack Overflow wrong?

The Rust language has been around for a number of years, and only reached version 1.0 in May of 2015. In the time before then the language changed significantly, and a number of Stack Overflow answers were given at the time of older versions of the language.

Over time more and more answers will be offered for the current version, thus improving this issue as the proportion of out-of-date answers is reduced.

Where do I report issues in the Rust documentation?

You can report issues in the Rust documentation on the Rust compiler issue tracker. Make sure to read the contributing guidelines first.

How do I view rustdoc documentation for a library my project depends on?

When you use cargo doc to generate documentation for your own project, it also generates docs for the active dependency versions. These are put into the target/doc directory of your project. Use cargo doc --open to open the docs after building them, or just open up target/doc/index.html yourself.