Hlavní navigace

Užitečné nástroje pro programovací jazyk Rust: rustup a rust-clippy

Pavel Tišnovský

Dnes se budeme věnovat popisu dvou užitečných nástrojů, které vývojáři používají prakticky denně. První slouží k rychlému přepínání mezi různými verzemi Rustu, druhý pak ve zdrojových kódech hledá potenciální problémy.

Obsah

1. Užitečné nástroje pro programovací jazyk Rust: rustup a rust-clippy

2. Nástroj rustup

3. Instalace nástroje rustup

4. Přepínání mezi stabilní verzí Rustu a nightly buildem

5. Aktualizace zvolené verze Rustu na poslední verzi

6. Struktura adresáře ~/.rustup

7. Clippy aneb lint na steroidech

8. Instalace nástroje Clippy

9. Spuštění Clippy nad projektem

10. Jednoduchý projekt na otestování základních chybových hlášení a varování

11. Chybová hlášení a varování vygenerovaná nástrojem Clippy

12. Základní detekované problémy

13. Kontrola operátorů a konstant

14. Kontrola chyb v rozhodovacích konstrukcích

15. Repositář s demonstračními příklady

16. Odkazy na Internetu

1. Užitečné nástroje pro programovací jazyk Rust: rustup a rust-clippy

Okolo programovacího jazyka Rust vznikl, podobně jako to můžeme vidět u prakticky každého jiného programovacího jazyka, ekosystém různých pomocných nástrojů určených jak pro podporu samotného vývoje, tak i pro testování aplikací, jejich balení, nasazení atd. V tomto seriálu už jsme se jedním z takových nástrojů zabývali. Jedná se o správce projektů Cargo, bez jehož pomoci by bylo poměrně obtížné vyvíjet aplikace, které vyžadují další podpůrné knihovny. Dnes si popíšeme další velmi užitečné nástroje, které možná budete používat prakticky každý den.

2. Nástroj rustup

První z těchto nástrojů se jmenuje rustup a slouží mj. ke snadnému přepínání mezi několika nainstalovanými verzemi překladače a běhového prostředí Rustu. S využitím rustup je také možné kdykoli překladač i běhové prostředí aktualizovat, a to i ve chvíli, kdy například ještě nejsou k dispozici balíčky pro danou distribuci Linuxu (a nutno říci, že zrovna v případě Rustu je pro správce balíčků poměrně problematické nezaostat za vývojem). Ve většině případů bývá výhodnější vůbec neinstalovat Rust z repositáře linuxové distribuce, ale použít namísto toho přímo rustup.

3. Instalace nástroje rustup

Nástroj rustup pravděpodobně ve vaší distribuci nenaleznete, popř. v ní bude jen starší verze této utility. Proto je lepší – i když méně bezpečné! – získat nejnovější verzi instalačního skriptu rustupu ze stránky https://www.rustup.rs/. Na této stránce se doporučuje použít příkaz:

$ curl https://sh.rustup.rs -sSf | sh

Bezpečnější je ovšem si nejdříve skript pouze stáhnout, přesvědčit se, že neprovádí žádné nebezpečné akce a spustit ho lokálně:

$ wget -O rustup.sh https://sh.rustup.rs
...
...
...
$ sh rustup.sh

Po spuštění instalačního skriptu se nejdříve stáhne vlastní instalátor (již pro danou architekturu a operační systém) a ten provede zbylé kroky instalace. Instalátor byl spuštěn pro uživatele tester, čemuž odpovídají všechny lokální cesty atd.:

info: downloading installer
 
Welcome to Rust!
 
This will download and install the official compiler for the Rust programming
language, and its package manager, Cargo.
 
It will add the cargo, rustc, rustup and other commands to Cargo's bin
directory, located at:
 
  /home/tester/.cargo/bin
 
This path will then be added to your PATH environment variable by modifying the
profile file located at:
 
  /home/tester/.profile
 
You can uninstall at any time with rustup self uninstall and these changes will
be reverted.
 
Current installation options:
 
   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable
  modify PATH variable: yes
 
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

Instalaci jsem schválně spustil před dvěma měsíci, aby bylo později možné otestovat, zda se provádí aktualizace:

info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: latest update on 2017-06-08, rust version 1.18.0 (03fc9d622 2017-06-06)
info: downloading component 'rustc'
 43.2 MiB /  43.2 MiB (100 %) 207.4 KiB/s ETA:   0 s
info: downloading component 'rust-std'
 72.2 MiB /  72.2 MiB (100 %) 944.0 KiB/s ETA:   0 s
info: downloading component 'cargo'
  4.9 MiB /   4.9 MiB (100 %) 947.0 KiB/s ETA:   0 s
info: downloading component 'rust-docs'
 11.7 MiB /  11.7 MiB (100 %) 937.6 KiB/s ETA:   0 s
info: installing component 'rustc'
info: installing component 'rust-std'
info: installing component 'cargo'
info: installing component 'rust-docs'
info: default toolchain set to 'stable'
 
  stable installed - rustc 1.18.0 (03fc9d622 2017-06-06)
 
 
Rust is installed now. Great!
 
To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done automatically.
 
To configure your current shell run source $HOME/.cargo/env

Nyní by měl být nainstalován jak překladač Rustu, tak i jeho běhové prostředí. Kromě toho se nainstaloval i správce projektů Cargo:

$ rustc --version
rustc 1.18.0 (03fc9d622 2017-06-06)
 
$ cargo --version
cargo 0.20.0 (a60d185c8 2017-07-13)

4. Přepínání mezi stabilní verzí Rustu a nightly buildem

Důležitá poznámka na začátek: instalace stabilní verze Rustu společně s nightly buildem bude na vašem disku vyžadovat přibližně jeden gigabajt prostoru. Instalace implicitně proběhne do adresáře .rustup umístěného ve vašem domácím adresáři, takže si prosím pomocí df zkontrolujte, zda máte na příslušném oddílu/LVM dostatek místa.

Již na konci předchozí kapitoly jsme si vyzkoušeli, jaká verze Rustu byla přes rustup nainstalována:

$ rustc --version
rustc 1.18.0 (03fc9d622 2017-06-06)

V mnoha případech, například při použití dále popsaného nástroje Clippy, je nutné použít takzvanou nightly verzi překladače, která je sice považována za nestabilní, ale obsahuje podporu pro nejnovější jazykové konstrukce, má pěknější systém hlášení chyb atd. Pokud pro instalaci nightly verze použijeme rustup, nebude tato instalace nijak kolidovat se stabilní verzí. Pusťme se tedy do toho:

$ rustup install nightly

Průběh instalace jak Rustu, tak i dalších podpůrných nástrojů (Cargo atd.):

info: syncing channel updates for 'nightly-x86_64-unknown-linux-gnu'
info: latest update on 2017-07-07, rust version 1.20.0-nightly (696412de7 2017-07-06)
info: downloading component 'rustc'
 38.7 MiB /  38.7 MiB (100 %) 928.0 KiB/s ETA:   0 s
info: downloading component 'rust-std'
 57.9 MiB /  57.9 MiB (100 %) 947.2 KiB/s ETA:   0 s
info: downloading component 'cargo'
  3.7 MiB /   3.7 MiB (100 %) 895.8 KiB/s ETA:   0 s
info: downloading component 'rust-docs'
  3.7 MiB /   3.7 MiB (100 %) 907.8 KiB/s ETA:   0 s
info: installing component 'rustc'
info: installing component 'rust-std'
info: installing component 'cargo'
info: installing component 'rust-docs'

Příkazem rustup default __verze__ se nyní můžeme snadno přepínat mezi stabilní verzí a nightly verzí. Můžeme se o tom snadno přesvědčit. Nejdříve se přepneme do stabilní verze:

$ rustup default stable
info: using existing install for 'stable-x86_64-unknown-linux-gnu'
info: default toolchain set to 'stable-x86_64-unknown-linux-gnu'
 
  stable-x86_64-unknown-linux-gnu unchanged - rustc 1.18.0 (03fc9d622 2017-06-06)

Aktivní verze překladače a nástroje Cargo:

$ rustc --version
rustc 1.18.0 (03fc9d622 2017-06-06)
 
$ cargo --version
cargo 0.20.0 (a60d185c8 2017-07-13)

Přepnutí na nightly verzi:

$ rustup default nightly
info: using existing install for 'nightly-x86_64-unknown-linux-gnu'
info: default toolchain set to 'nightly-x86_64-unknown-linux-gnu'
 
  nightly-x86_64-unknown-linux-gnu unchanged - rustc 1.20.0-nightly (696412de7 2017-07-06)

Aktivní verze překladače a nástroje Cargo se nyní podle očekávání změnila:

$ rustc --version
rustc 1.20.0-nightly (696412de7 2017-07-06)
 
$ cargo --version
cargo 0.22.0-nightly (305bc25d5 2017-07-28)

5. Aktualizace zvolené verze Rustu na poslední verzi

Pro výpis aktuálně používané verze použijeme tento příkaz:

$ rustup show

Na standardní výstup by se měly vypsat následující řádky, z nichž nás zajímá především sekce active toolchain:

Default host: x86_64-unknown-linux-gnu
 
installed toolchains
--------------------
 
stable-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)
 
active toolchain
----------------
 
nightly-x86_64-unknown-linux-gnu (default)
rustc 1.20.0-nightly (696412de7 2017-07-06)

Pokud budete chtít provést aktualizaci na poslední nightly verzi, provede se to velmi snadno příkazem:

$ rustup update

Tento příkaz stáhne dalších zhruba 300–500 MB (aktualizace jedné verze), popř. až 1 GB (aktualizace obou verzí)!

info: latest update on 2017-08-08, rust version 1.21.0-nightly (cbbe17aa7 2017-08-07)
info: downloading component 'rustc'
...
...
...
   stable-x86_64-unknown-linux-gnu updated - rustc 1.19.0 (0ade33941 2017-07-17)
     nightly-x86_64-unknown-linux-gnu updated - rustc 1.21.0-nightly (cbbe17aa7 2017-08-07)

6. Struktura adresáře ~/.rustup

Jak jsme si již řekli výše, používá nástroj rustup jako pracovní adresář ~/.rustup (ostatně proto taky nikde nepoužíváme sudo ani su). Pojďme se tedy podívat, jak vypadá struktura tohoto adresáře. Nebudou nás zajímat všechny podrobnosti, takže stromovou strukturu vypíšeme jen pro první tři úrovně:

$ tree -L 3 ~/.rustup

Tento podadresář vypadá zhruba takto (samozřejmě na odlišné architektuře se budou podadresáře jmenovat jinak):

/home/tester/.rustup
├── downloads
├── settings.toml
├── tmp
├── toolchains
│   ├── nightly-x86_64-unknown-linux-gnu
│   │   ├── bin
│   │   ├── etc
│   │   ├── lib
│   │   └── share
│   └── stable-x86_64-unknown-linux-gnu
│       ├── bin
│       ├── etc
│       ├── lib
│       └── share
└── update-hashes
    ├── nightly-x86_64-unknown-linux-gnu
    └── stable-x86_64-unknown-linux-gnu
 
14 directories, 3 files

Aktuální nastavení je uloženo v souboru settings.toml.

Při výběru nightly verze:

default_host_triple = "x86_64-unknown-linux-gnu"
default_toolchain = "nightly-x86_64-unknown-linux-gnu"
telemetry = false
version = "12"
 
[overrides]

Při výběru stabilní verze:

default_host_triple = "x86_64-unknown-linux-gnu"
default_toolchain = "stable-x86_64-unknown-linux-gnu"
telemetry = false
version = "12"
 
[overrides]

7. Clippy aneb lint na steroidech

Druhý nástroj, s nímž se dnes alespoň ve stručnosti seznámíme, se jmenuje rust-clippy popř. zkráceně jen clippy. Tuto užitečnou utilitu je možné použít pro hledání potenciálních chyb ve zdrojových kódech popř. pro nalezení takových obratů a jazykových konstrukcí, které jsou z různých důvodů neefektivní či které nejsou pro Rust idiomatické. Utilita rust-clippy tedy nahrazuje především klasický lint (linter), ovšem z vypisovaných varování se můžeme dozvědět i mnohé zajímavé informace o způsobu práce s proměnnými, funkci pattern matchingu apod. Mimochodem – tuto utilitu si můžeme vyzkoušet i bez nutnosti její instalace, protože je dostupná (společně s automatickým formátovačem zdrojového kódu) například i ve „webovém IDE pro Rust“, které naleznete na adrese https://play.rust-lang.org/.

8. Instalace nástroje Clippy

Nástroj Clippy vyžaduje poslední nightly verzi jazyka Rust a jeho běhového prostředí. Pokud jste si prošli předchozí kapitoly, máte nejaktuálnější verzi již nainstalovanou, takže se do ní jen přepneme:

$ rustup default nightly
info: using existing install for 'nightly-x86_64-unknown-linux-gnu'
info: default toolchain set to 'nightly-x86_64-unknown-linux-gnu'
 
  nightly-x86_64-unknown-linux-gnu unchanged - rustc 1.20.0-nightly (cbbe17aa7 2017-08-07)

Pro jistotu si verzi ještě jednou zkontrolujeme

$ rustc --version
rustc 1.21.0-nightly (cbbe17aa7 2017-08-07)

Ve skutečnosti existuje hned několik možností, jak nástroj Clippy nainstalovat a používat; nejjednodušší je však jeho instalace s využitím správce projektů Cargo. Posléze bude možné Clippy používat, aniž by bylo nutné upravovat projektové soubory. Instalace se provede snadno:

$ cargo install clippy
    Updating registry `https://github.com/rust-lang/crates.io-index`
  Installing clippy v0.0.149
   Compiling unicode-xid v0.0.4
   Compiling serde v1.0.11
   Compiling lazy_static v0.2.8
   Compiling quine-mc_cluskey v0.2.4
   Compiling either v1.1.0
   Compiling unicode-normalization v0.1.5
   Compiling matches v0.1.6
   Compiling itoa v0.3.1
   Compiling num-traits v0.1.40
   Compiling quote v0.3.15
   Compiling pulldown-cmark v0.0.15
   Compiling semver-parser v0.7.0
   Compiling getopts v0.2.14
   Compiling regex-syntax v0.4.1
   Compiling dtoa v0.4.1
   Compiling bitflags v0.9.1
   Compiling synom v0.11.3
   Compiling itertools v0.6.1
   Compiling semver v0.6.0
   Compiling serde_json v1.0.2
   Compiling toml v0.4.4
   Compiling syn v0.11.11
   Compiling serde_derive_internals v0.15.1
   Compiling serde_derive v1.0.11
   Compiling cargo_metadata v0.2.3
   Compiling clippy_lints v0.0.149
   Compiling clippy v0.0.149
    Finished release [optimized] target(s) in 296.89 secs
  Installing /home/tester/.cargo/bin/cargo-clippy

Pokud se instalace nepodaří, bude to velmi pravděpodobně kvůli chybám při překladu balíčků clippy_lints nebo clippy. V tom případě si prosím ještě jednou zkontrolujte, zda máte aktualizovanou nightly verzi Rustu a jestli je tato verze implicitně používána.

9. Spuštění Clippy nad projektem

Po (doufejme) úspěšné instalaci je možné Clippy spustit nad prakticky jakýmkoli projektem spravovaným systémem Cargo. Základní příkaz pro spuštění vypadá následovně:

$ cargo clippy

Pozor: Clippy kromě kontroly provádí i překlad, takže pokud stejný příkaz spustíte znovu, zdánlivě se již nic neprovede, neboť mezitím nedošlo ke změně zdrojových kódů:

$ cargo clippy
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs

Použijte například:

$ cargo clean;cargo clippy

Nástroji Clippy je možné předávat různé parametry, které ovlivňují, které programové konstrukce a obraty budou považovány za chyby či u kterých se vypíše varování. Implicitní nastavení je popsané na stránce https://github.com/rust-lang-nursery/rust-clippy/wiki. Pokud například budete chtít, aby se chybějící podtržítko mezi numerickou konstantou a uvedením typu konstanty hlásilo jako varování (warning), lze to provést následovně:

$ cargo clippy -- -W unseparated_literal_suffix

(viz též podrobnější popis uvedený na https://github.com/rust-lang-nursery/rust-clippy/wiki#unseparated_li­teral_suffix)

10. Jednoduchý projekt na otestování základních chybových hlášení a varování

Podívejme se nyní na jednoduchý projekt, který neobsahuje žádné chyby hlášené překladačem, ovšem je v něm poměrně hodně potenciálně problematických či neidiomatických míst. Dokážete je najít?

fn main() {
    print!("Hello, world!\n");
 
    let mut a = 123456789;
    let mut b = 123i32;
 
    println!("{}", a);
    println!("{}", b);
 
    a = a + 1;
    println!("{}", a);
 
    b = 2 * b;
    println!("{}", b);
 
    let foo = 42;
    println!("{}", foo);
 
    let pi = 3.14;
    println!("{}", pi);
 
    let e = 2.718;
    println!("{}", e);
 
    let s = 1.4142;
    println!("{}", s);
 
    let x = true;
 
    if x == true {
        println!("T");
    }
 
    if x == false {
        println!("nil");
    }
 
    println!("{}",
        match x {
            true => 1,
            false => 2
        }
    );
}

11. Chybová hlášení a varování vygenerovaná nástrojem Clippy

Zkusme si nyní tento projekt přeložit a současně i analyzovat nástrojem Clippy:

$ cargo clippy

Výsledek může být (na tak jednoduchý projekt) až překvapující:

   Compiling clippy-test v0.1.0 (file:///home/tester/rust/projects/clippy-test)
warning: 5th binding whose name is just one char
  --> src/main.rs:28:9
   |
28 |     let x = true;
   |         ^
   |
   = note: #[warn(many_single_char_names)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#many_single_char_names
 
warning: long literal lacking separators
 --> src/main.rs:4:17
  |
4 |     let mut a = 123456789;
  |                 ^^^^^^^^^
  |
  = note: #[warn(unreadable_literal)] on by default
  = help: consider: 123_456_789
  = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unreadable_literal
 
warning: using `print!()` with a format string that ends in a newline, consider using `println!()` instead
 --> src/main.rs:2:5
  |
2 |     print!("Hello, world!\n");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(print_with_newline)] on by default
  = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#print_with_newline
 
warning: manual implementation of an assign operation
  --> src/main.rs:10:5
   |
10 |     a = a + 1;
   |     ^^^^^^^^^ help: replace it with: `a += 1`
   |
   = note: #[warn(assign_op_pattern)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern
 
warning: manual implementation of an assign operation
  --> src/main.rs:13:5
   |
13 |     b = 2 * b;
   |     ^^^^^^^^^ help: replace it with: `b *= 2`
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#assign_op_pattern
 
warning: use of a blacklisted/placeholder name `foo`
  --> src/main.rs:16:9
   |
16 |     let foo = 42;
   |         ^^^
   |
   = note: #[warn(blacklisted_name)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#blacklisted_name
 
warning: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
  --> src/main.rs:19:14
   |
19 |     let pi = 3.14;
   |              ^^^^
   |
   = note: #[warn(approx_constant)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#approx_constant
 
warning: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
  --> src/main.rs:22:13
   |
22 |     let e = 2.718;
   |             ^^^^^
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#approx_constant
 
warning: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly
  --> src/main.rs:25:13
   |
25 |     let s = 1.4142;
   |             ^^^^^^
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#approx_constant
 
warning: equality checks against true are unnecessary
  --> src/main.rs:30:8
   |
30 |     if x == true {
   |        ^^^^^^^^^ help: try simplifying it as shown: `x`
   |
   = note: #[warn(bool_comparison)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison
 
warning: equality checks against false can be replaced by a negation
  --> src/main.rs:34:8
   |
34 |     if x == false {
   |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#bool_comparison
 
warning: you seem to be trying to match on a boolean expression
  --> src/main.rs:39:9
   |
39 | /         match x {
40 | |             true => 1,
41 | |             false => 2
42 | |         }
   | |_________^ help: consider using an if/else expression: `if x { 1 } else { 2 }`
   |
   = note: #[warn(match_bool)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#match_bool
 
    Finished dev [unoptimized + debuginfo] target(s) in 0.63 secs

12. Základní detekované problémy

Příklad byl zcela záměrně vytvořen takovým způsobem, aby se v něm nacházely jen snadno popsatelné problémy :-), takže si je nyní ve stručnosti popišme:

  • Provádí se kontrola, kolik je v bloku (typicky ve funkci) použito pět jednoznakových identifikátorů. Limitní hodnotou je 5 (lze změnit). Větší počet naznačuje, že je funkce příliš složitá a měl by se provést refaktoring či alespoň proměnným přiřadit „rozumná“ jména. V příkladu je použito právě pět jednoznakových konstant.
  • Podobně se testuje počet parametrů funkce, kde je limit stanoven na sedm parametrů. Větší počet parametrů vede k potenciálně špatně čitelnému kódu, především při volání takových funkcí.
  • I některé víceznakové názvy proměnných mohou být problematické, takže Clippy obsahuje konfigurovatelný seznam jmen, mezi něž patří například ifoo atd. Použití takových jmen může značit buď copy&paste kódu nebo to, že se programátor moc nezamýšlí nad čitelností.
  • Použití makra print!(„řetězec\n“) by mělo být nahrazeno makrem println!(„řetězec“), aneb nemá smysl zbytečně komplikovat zápis řetězce s řídicími znaky, když pro odřádkování existuje speciální makro. I tuto chybu máme v našem příkladu zavedenu.

13. Kontrola operátorů a konstant

Další kontroly se týkají zápisu operátorů a konstant:

  • Provádí se kontrola na konstanty začínající nulou. Ty jsou potenciálně velmi problematické, protože v jazyku C jsou konstanty začínající nulou reprezentovány v osmičkové soustavě, kdežto v Rustu v soustavě desítkové! Proto jsou zápisy s nulou na začátku jak špatně čitelné (hlavně pro céčkaře), tak i potenciálně chybné ve chvíli, kdy kód vznikl transformací z céčka.
  • Lze zapnout kontrolu pro oddělení typu konstanty od vlastní konstanty: 123i32 versus 123_i32, což je nejenom čitelnější, ale zabraňuje to vzniku špatně dohledatelných chyb.
  • Dále se testuje, zda dlouhé číselné konstanty obsahují znak podtržítka, což zvyšuje čitelnost. Typicky se podtržítko vkládá jako oddělovač miliard, milionů a tisíců, tedy například: 123_456_789, v našem příkladu však máme jen 123456789.
  • Velmi zajímavá je detekce známých konstant typu π, e, √2, resp. hodnot, které se těmto konstantám podobají. U takových hodnot je doporučeno použít konstanty z modulů f32 a f64. V příkladu máme hned několik takových konstant let pi = 3.14, let e = 2.718 a let s = 1.4142.
  • Taktéž se kontrolují zápisy typu a = a + 1, které jdou nahradit za a += 1. Totéž platí i v případě zápisu b = 2 * b, protože v tomto případě je operátor * komutativní, což Clippy rozpozná (někdy však test proběhne špatně, například při implementaci traitu pro operátor * aplikovaný pro matice).
  • Dále se testuje použití operátorů == a != pro dvě konstanty/proměnné typuf32 a f64, protože tato porovnání je lepší explicitně provádět se specifikovanou povolenou odchylkou. Jediné porovnání, které se nehlásí jako chyba, je porovnání konstanty s nulou.
  • Provádí se i kontrola, zda se na obou stranách některých operátorů (typicky ==, ale i && či -) nenachází stejné operandy nebo celé výrazy. Typicky se jedná o výsledek copy&paste.
  • Kontroluje se zápis –x, který má v Rustu význam změny znaménka provedené dvakrát, nikoli operace dekrementace!

14. Kontrola chyb v rozhodovacích konstrukcích

Další sada testů se týká chyb v logických konstrukcích, například:

  • Podmínka typu x == true či x == false patří mezi typické „školácké chyby“, které Clippy snadno odhalí a nabídne použití x nebo !x.
  • Zajímavější je detekce stavu, kdy lze konstrukci match nahradit za pouhý výraz s if-then-else.
  • Totéž platí pro náhradu konstrukce match a if let, ovšem tato kontrola je implicitně vypnuta.
  • Podobně se nabízí náhrada konstrukce loop+match za kratší konstrukci while let.
  • Naopak konstrukci typu while let Some(val) = iter() je lepší přepsat na mnohem čitelnější smyčku typu for-each.

15. Repositář s demonstračními příklady

Jediný dnes použitý projekt naprogramovaný v Rustu byl, ostatně podobně jako ve všech předchozích částech tohoto seriálu, uložen do Git repositáře dostupného na adrese https://github.com/tisnik/pre­sentations. Demonstrační příklad si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář (ovšem u projektů je lepší mít celý repositář, abyste nemuseli pracně stahovat všechny potřebné soubory):

16. Odkazy na Internetu

  1. Rust-clippy Wiki
    https://github.com/rust-lang-nursery/rust-clippy/wiki
  2. Rust-clippy
    https://rust.libhunt.com/project/rust-clippy
  3. ndarray – dokumentace
    https://bluss.github.io/rust-ndarray/master/ndarray/index.html
  4. ndarray – Crate
    https://crates.io/crates/ndarray
  5. rustup
    https://www.rustup.rs/
  6. rustup: the Rust toolchain installer (Git repositář + dokumentace)
    https://github.com/rust-lang-nursery/rustup.rs
  7. The Rust FFI Omnibus
    http://jakegoulding.com/rust-ffi-omnibus/
  8. Build Script Support
    http://doc.crates.io/build-script.html
  9. Calling Rust From Python
    https://bheisler.github.i­o/post/calling-rust-in-python/
  10. Calling Rust in Python (komentáře k předchozímu článku)
    https://www.reddit.com/r/rus­t/comments/63iy5a/calling_rus­t_in_python/
  11. CFFI Documentation
    https://cffi.readthedocs.i­o/en/latest/
  12. Build Script Support
    http://doc.crates.io/build-script.html
  13. Creating a shared and static library with the gnu compiler [gcc]
    http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
  14. ctypes — A foreign function library for Python
    https://docs.python.org/2/li­brary/ctypes.html
  15. FFI: Foreign Function Interface
    https://doc.rust-lang.org/book/ffi.html
  16. Primitive Type pointer
    https://doc.rust-lang.org/std/primitive.pointer.html
  17. Cargo: správce projektů a balíčků pro programovací jazyk Rust
    https://mojefedora.cz/cargo-spravce-projektu-a-balicku-pro-programovaci-jazyk-rust/
  18. Network Communication and Serialization in Rust
    https://www.safaribookson­line.com/blog/2014/01/28/net­work-communication-serialization-rust/
  19. Crate bincode
    http://tyoverby.com/binco­de/bincode/index.html
  20. Struct std::fs::File
    https://doc.rust-lang.org/std/fs/struct.File.html
  21. Trait std::io::Seek
    https://doc.rust-lang.org/std/io/trait.Seek.html
  22. Trait std::io::Read
    https://doc.rust-lang.org/std/io/trait.Read.html
  23. Trait std::io::Write
    https://doc.rust-lang.org/std/io/trait.Write.html
  24. Trait std::io::BufRead
    https://doc.rust-lang.org/std/io/trait.BufRead.html
  25. Module std::io::prelude
    https://doc.rust-lang.org/std/io/prelude/index.html
  26. std::net::IpAddr
    https://doc.rust-lang.org/std/net/enum.IpAddr.html
  27. std::net::Ipv4Addr
    https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
  28. std::net::Ipv6Addr
    https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
  29. TcpListener
    https://doc.rust-lang.org/std/net/struct.TcpLis­tener.html
  30. TcpStream
    https://doc.rust-lang.org/std/net/struct.TcpStream.html
  31. Binary heap (Wikipedia)
    https://en.wikipedia.org/wi­ki/Binary_heap
  32. Binární halda (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Bin%C3%A1rn%C3%AD_halda
  33. Halda (datová struktura)
    https://cs.wikipedia.org/wi­ki/Halda_%28datov%C3%A1_struk­tura%29
  34. Struct std::collections::HashSet
    https://doc.rust-lang.org/std/collections/struc­t.HashSet.html
  35. Struct std::collections::BTreeSet
    https://doc.rust-lang.org/std/collections/struc­t.BTreeSet.html
  36. Struct std::collections::BinaryHeap
    https://doc.rust-lang.org/std/collections/struc­t.BinaryHeap.html
  37. Set (abstract data type)
    https://en.wikipedia.org/wi­ki/Set_%28abstract_data_ty­pe%29#Language_support
  38. Associative array
    https://en.wikipedia.org/wi­ki/Associative_array
  39. Hash Table
    https://en.wikipedia.org/wi­ki/Hash_table
  40. B-tree
    https://en.wikipedia.org/wiki/B-tree
  41. Pedro Celis: Robin Hood Hashing (naskenované PDF!)
    https://cs.uwaterloo.ca/re­search/tr/1986/CS-86–14.pdf
  42. Robin Hood hashing
    http://codecapsule.com/2013/11/11/ro­bin-hood-hashing/
  43. Robin Hood hashing: backward shift deletion
    http://codecapsule.com/2013/11/17/ro­bin-hood-hashing-backward-shift-deletion/
  44. Module std::collections
    https://doc.rust-lang.org/std/collections/
  45. Module std::vec
    https://doc.rust-lang.org/nightly/std/vec/index.html
  46. Struct std::collections::VecDeque
    https://doc.rust-lang.org/std/collections/struc­t.VecDeque.html
  47. Struct std::collections::LinkedList
    https://doc.rust-lang.org/std/collections/struc­t.LinkedList.html
  48. Module std::fmt
    https://doc.rust-lang.org/std/fmt/
  49. Macro std::println
    https://doc.rust-lang.org/std/macro.println.html
  50. Enum std::result::Result
    https://doc.rust-lang.org/std/result/enum.Result.html
  51. Module std::result
    https://doc.rust-lang.org/std/result/
  52. Result
    http://rustbyexample.com/std/re­sult.html
  53. Rust stdlib: Option
    https://doc.rust-lang.org/std/option/enum.Option.html
  54. Module std::option
    https://doc.rust-lang.org/std/option/index.html
  55. Rust by example: option
    http://rustbyexample.com/std/op­tion.html
  56. Rust by example: if-let
    http://rustbyexample.com/flow_con­trol/if_let.html
  57. Rust by example: while let
    http://rustbyexample.com/flow_con­trol/while_let.html
  58. Rust by example: Option<i32>
    http://rustbyexample.com/std/op­tion.html
  59. An Overview of Macros in Rust
    http://words.steveklabnik.com/an-overview-of-macros-in-rust
  60. A Practical Intro to Macros in Rust 1.0
    https://danielkeep.github.io/practical-intro-to-macros.html
  61. The Rust Programming Language: macros
    https://doc.rust-lang.org/beta/book/macros.html
  62. Rust by example: 15 macro_rules!
    http://rustbyexample.com/macros.html
  63. Primitive Type isize
    https://doc.rust-lang.org/nightly/std/primi­tive.isize.html
  64. Primitive Type usize
    https://doc.rust-lang.org/nightly/std/primi­tive.usize.html
  65. Primitive Type array
    https://doc.rust-lang.org/nightly/std/primi­tive.array.html
  66. Module std::slice
    https://doc.rust-lang.org/nightly/std/slice/
  67. Rust by Example: 2.3 Arrays and Slices
    http://rustbyexample.com/pri­mitives/array.html
  68. What is the difference between Slice and Array (stackoverflow)
    http://stackoverflow.com/qu­estions/30794235/what-is-the-difference-between-slice-and-array
  69. Learning Rust With Entirely Too Many Linked Lists
    http://cglab.ca/~abeinges/blah/too-many-lists/book/
  70. Testcase: linked list
    http://rustbyexample.com/cus­tom_types/enum/testcase_lin­ked_list.html
  71. Operators and Overloading
    https://doc.rust-lang.org/book/operators-and-overloading.html
  72. Module std::ops
    https://doc.rust-lang.org/std/ops/index.html
  73. Module std::cmp
    https://doc.rust-lang.org/std/cmp/index.html
  74. Trait std::ops::Add
    https://doc.rust-lang.org/stable/std/ops/trait.Add.html
  75. Trait std::ops::AddAssign
    https://doc.rust-lang.org/std/ops/trait.AddAssign.html
  76. Trait std::ops::Drop
    https://doc.rust-lang.org/std/ops/trait.Drop.html
  77. Trait std::cmp::Eq
    https://doc.rust-lang.org/std/cmp/trait.Eq.html
  78. Struct std::boxed::Box
    https://doc.rust-lang.org/std/boxed/struct.Box.html
  79. Explore the ownership system in Rust
    https://nercury.github.io/rus­t/guide/2015/01/19/ownership­.html
  80. Rust's ownership and move semantic
    http://www.slideshare.net/sa­neyuki/rusts-ownership-and-move-semantics
  81. Trait std::marker::Copy
    https://doc.rust-lang.org/stable/std/marker/tra­it.Copy.html
  82. Trait std::clone::Clone
    https://doc.rust-lang.org/stable/std/clone/tra­it.Clone.html
  83. The Stack and the Heap
    https://doc.rust-lang.org/book/the-stack-and-the-heap.html
  84. Rust Compare: Pointers & References
    http://www.rust-compare.com/site/pointers.html
  85. Rust Compare: Parameters
    http://www.rust-compare.com/site/params.html
  86. Why does this compile? Automatic dereferencing?
    https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183
  87. Understanding Pointers, Ownership, and Lifetimes in Rust
    http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html
  88. Rust lang series episode #25 — pointers (#rust-series)
    https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series
  89. Rust – home page
    https://www.rust-lang.org/en-US/
  90. Rust – Frequently Asked Questions
    https://www.rust-lang.org/en-US/faq.html
  91. Destructuring and Pattern Matching
    https://pzol.github.io/get­ting_rusty/posts/20140417_des­tructuring_in_rust/
  92. The Rust Programming Language
    https://doc.rust-lang.org/book/
  93. Rust (programming language)
    https://en.wikipedia.org/wi­ki/Rust_%28programming_lan­guage%29
  94. Go – home page
    https://golang.org/
  95. Stack Overflow – Most Loved, Dreaded, and Wanted language
    https://stackoverflow.com/re­search/developer-survey-2016#technology-most-loved-dreaded-and-wanted
  96. Rust vs Go (dva roky staré hodnocení, od té doby došlo k posunům v obou jazycích)
    http://jaredforsyth.com/2014/03/22/rust-vs-go/
  97. Rust vs Go: My experience
    https://www.reddit.com/r/go­lang/comments/21m6jq/rust_vs_go_my_ex­perience/
  98. Friends of Rust (Organizations running Rust in production)
    https://www.rust-lang.org/en-US/friends.html
  99. Rust programs versus C++ g++
    https://benchmarksgame.ali­oth.debian.org/u64q/compa­re.php?lang=rust&lang2=gpp
  100. Další benchmarky (nejedná se o reálné příklady „ze života“)
    https://github.com/kostya/benchmarks
  101. Go na Redditu
    https://www.reddit.com/r/golang/
  102. Rust vs. Go
    http://vschart.com/compare/rust/vs/go-language
  103. Abstraction without overhead: traits in Rust
    https://blog.rust-lang.org/2015/05/11/traits.html
  104. Method Syntax
    https://doc.rust-lang.org/book/method-syntax.html
  105. Traits in Rust
    https://doc.rust-lang.org/book/traits.html
  106. Functional Programming in Rust – Part 1 : Function Abstraction
    http://blog.madhukaraphatak­.com/functional-programming-in-rust-part-1/
  107. Of the emerging systems languages Rust, D, Go and Nim, which is the strongest language and why?
    https://www.quora.com/Of-the-emerging-systems-languages-Rust-D-Go-and-Nim-which-is-the-strongest-language-and-why
  108. Chytré ukazatele (moderní verze jazyka C++) [MSDN]
    https://msdn.microsoft.com/cs-cz/library/hh279674.aspx
  109. UTF-8 Everywhere
    http://utf8everywhere.org/
  110. Rust by Example
    http://rustbyexample.com/
  111. Rust oficiálně ve Fedoře
    https://mojefedora.cz/rust-oficialne-ve-fedore/
  112. Resource acquisition is initialization
    https://en.wikipedia.org/wi­ki/Resource_acquisition_is_i­nitialization
  113. TIOBE index (October 2016)
    http://www.tiobe.com/tiobe-index/
  114. Porovnání Go, D a Rustu na OpenHubu:
    https://www.openhub.net/lan­guages/compare?language_na­me[]=-1&language_name[]=-1&language_name[]=dmd&lan­guage_name[]=golang&langu­age_name[]=rust&language_na­me[]=-1&measure=commits
  115. String Types in Rust
    http://www.suspectsemantic­s.com/blog/2016/03/27/str­ing-types-in-rust/
  116. Trait (computer programming)
    https://en.wikipedia.org/wi­ki/Trait_%28computer_program­ming%29
  117. Type inference
    https://en.wikipedia.org/wi­ki/Type_inference
Našli jste v článku chybu?