Rustでよく見かけるattributeを整理する。

これは[Rust その2 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/rust-lang-2) 15日目の記事です。
公開が遅れてしまったため、日付と記事公開日は合っていません。

このエントリではRustのmod、crateなどに対するメタデータであるアトリビュートについて整理した。
アトリビュートの書き方は大きく分けて下記の２つがある。

 - !を入れると囲んでいるアイテムへの適用

```rust
mod foo {
    #![foo]
}
```
 - !がない書き方だと次の宣言への適用

```rust
#[bar]
struct bar;
```
#crate_type, crate_name
crate_typeアトリビュートは、そのクレイトがライブラリ、バイナリのいずれにコンパイルされるべきかをコンパイラに伝えるために使用。
crate_nameはクレイトの名前を決定するのに使用。

```rust
#![crate_type = "lib"]
#![crate_name = "rary"]
```
crate_type宣言しておけば、コンパイル時に--crate-typeフラグを付ける必要がない。
crate_typeの一覧は[こちら](https://doc.rust-lang.org/reference/linkage.html)

```bash
$ rustc lib.rs
$ ls lib*
library.rlib
```

#feature
主にnightlyの機能を実装する際、下記のような設定でfeature機能を使える。

```rust
#![feature(feature1, feature2, feature3)]
```
指定できる値の一覧は[こちら](https://doc.rust-lang.org/reference.html#compiler-features)

#allow
lintチェックをエラーにせず、許容するアトリビュートです。以下の２種類を紹介する。

```rust
#[allow(dead_code)]
fn unused_function() {}
```
コンパイラは使用されていない関数が存在するときに警告を出す。
dead_codeによってこの機能を無効化することができる。

```rust
#[allow(non_camel_case_types)]
type int8_t = i8;
```
typeエイリアスはCamelCaseで書くことが推奨されていますが、それ以外の書き方をしたい場合には `non_camel_case_types`で警告を無効化できる。

#test
test_foo関数テストを走らせた時に実行されるというテスト関数になる。
通常通りにコンパイルをした場合は、コンパイル結果に含まれない。

```rust
#[test]
fn test_foo(){
	/* ... */
}
```
#macro_use
全てのマクロがロードされる。
extern crateの上で利用すると、外部のクレートからどのマクロをロードするのかを指定できる。

```rust
#[macro_use(hoge, fuga)]
extern crate foo;
```

#derive
毎回Debugなどのトレイトを実装するを避けるために、自動的にトレイトを実装するためのderiveアトリビュートがある。
コンパイラには、deriveアトリビュートを用いることで型に対して特定のトレイトの標準的な実装を提供できる。

```rust
#[derive(Debug)]
struct Foo;

fn main() {
    println!("{:?}", Foo);
}
```
標準で実装されているトレイトは以下の一覧。

- [Clone](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/clone/trait.Clone.html)
- [Copy](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/marker/trait.Copy.html)
- [Debug](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/fmt/trait.Debug.html)
- [Default](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/default/trait.Default.html)
- [Eq](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/cmp/trait.Eq.html)
- [Hash](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/hash/trait.Hash.html)
- [Ord](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/cmp/trait.Ord.html)
- [PartialEq](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/cmp/trait.PartialEq.html)
- [PartialOrd](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/core/cmp/trait.PartialOrd.html)



#cfg
同じコードで複数の環境に合わせてコンパイル結果を得たい時は、cfgアトリビュートでコンパイラにフラグを渡すことが出来る。

```rust
#[cfg(target_os="linux")]
fn target_on_linux(){
	println!("Running linux.")
}

#[cfg(not(target_os = "linux"))]
fn no_target_on_linux(){
	println!("Not running linux.")
}
```
条件を独自に追加する場合は--cfgフラグを用いてコンパイラに伝える必要がある。

```rust
#[cfg(feature = "nightly")]
fn conditional_function() {
    println!("condition met!")
}
```
```bash
$ rustc --cfg nightly custom.rs
```
#cfg!
cfg!マクロではコード中にフラグを利用することができる。
コンパイル時にtrueかfalseを返す。

```rust
if cfg!(target_os = "linux") {
	println!("Yes. It's definitely linux!");
} else {
	println!("Yes. It's definitely *not* linux!");
}
```

#cfg_attr
cfg_attr を用いることで、cfg に設定された値によってアトリビュートを有効にすることが出来る。
cfg アトリビュートによって a が有効になっている場合に限り #[b] と設定されている 場合と同じ意味。

```rust
#![cfg_attr(feature="clippy", feature(plugin))]
```