Rust 1.29.0 is out!

See the blog post and detailed release notes. The major new features are cargo fix and cargo clippy.

7 Likes
fn main() {
    for _i in 0..100 {
        do_something();
    }
}

In that case in Rust I write:

for _ in 0 .. 100 {

No need for an underscored name.

Iterator::flatten

I'd like to see code that uses this iterator. I think in most cases you can rewrite the code in a better way in Rust.

1 Like

That is semantically different though, as binding to _ drops the value right away. That makes no difference for integers, of course, nor any other Copy type. So your preference is fine, but the compiler needs to be careful about what changes it suggests.

4 Likes

I see, so I guess it's a matter of having a more specialized error message.

As an aside, the release blog mentions that 1.30 and 1.31 will be huge releases.
Is there any way I can see what's lined up for them?

1 Like

I've just tried 1.29 on one of my projects and am getting errors that I've never seen before and don't understand (line breaks inserted):

V:\diff>rustc -V
rustc 1.29.0 (aa3ca1994 2018-09-11)

V:\diff>cargo update
    Updating registry `https://github.com/rust-lang/crates.io-index`
...elided additions/removals/updates...
V:\diff>cargo build --release --verbose
   Compiling version_check v0.1.4
     Running `rustc --crate-name version_check
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823
\version_check-0 1.4\src\lib.rs --crate-type lib 
--emit=dep-info,link -C opt-level=3 -C codegen-units=1 
-C metadata=f9a4bdd753b3ecaf 
-C extra filename=-f9a4bdd753b3ecaf 
--out-dir V:\diff\target\release\deps 
-L dependency=V:\diff\target\release\deps --cap lints allow 
-Ctarget-feature=+crt-static`
   Compiling cfg-if v0.1.5
     Running `rustc --crate-name cfg_if 
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823
\cfg-if-0.1.5\src\lib.r --crate-type lib --emit=dep-info,link 
-C opt-level=3 -C codegen-units=1 -C metadata=50007930382e66ba 
-C extra-filename=-500 7930382e66ba 
--out-dir V:\diff\target\release\deps 
-L dependency=V:\diff\target\release\deps --cap-lints allow 
-target-feature=+crt-static`
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `cfg-if`.

Caused by:
  process didn't exit successfully: `rustc --crate-name cfg_if 
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823 
cfg-if-0.1.5\src\lib.rs --crate-type lib --emit=dep-info,link 
-C opt-level=3 -C codegen-units=1 
-C metadata=50007930382e66ba 
-C extra-filename=-50007930382e66ba 
--out-dir V:\diff\target\release\deps 
-L dependency=V:\diff\target\release\dps --cap-lints allow 
-Ctarget-feature=+crt-static` (exit code: 1)
warning: build failed, waiting for other jobs to finish...
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `version_check`.

Caused by:
  process didn't exit successfully: `rustc --crate-name version_check 
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299d 
9ec823\version_check-0.1.4\src\lib.rs --crate-type lib 
--emit=dep-info,link -C opt-level=3 -C codegen-units=1 
-C metadata=f9 4bdd753b3ecaf 
-C extra-filename=-f9a4bdd753b3ecaf 
--out-dir V:\diff\target\release\deps 
-L dependency=V:\diff\taget\release\deps --cap-lints allow
-Ctarget-feature=+crt-static` (exit code: 1)

Here are the project's dependencies (excl. local ones):

chrono = { version = "0.4", features = ["serde"] }
error-chain = "0.12"
fnv = "1"
image = "0.18"
imageproc = "0.14"
lazy_static = "1"
rayon = "1"
regex = "1"
rusttype = "0.4"
serde = "1"
serde_derive = "1"
serde_json = "1"
walkdir = "2"

This is on Windows 7-64.

I think that the problem is due to a lazy_static dependency, but I don't know.

Fortunately I tested in a VM and have now restored the previous snapshot with 1.28. But until this is fixed I can't upgrade to the "small" 1.29 release, let alone the bigger ones in the works.

1.31 is edition 2018 (will be in 1.30 beta too.)
Items not specific to the new edition get passed to stable 1.30. NLL is possibly the big one.

1 Like

You've mixed a rustc update and a cargo update of your dependencies at the same time. Does your code compile ok with rust 1.28 and cargo update?

FWIW, https://github.com/rust-lang/rust/commit/a6adeae104c7dcc20025d92b984fd56427d93c1f breaks a build I have - should be an easy fix, but still. I didn't see that change mentioned in the relnotes :man_shrugging:

Yes.

Furthermore...
I tried again with 1.29 on Windows 7-64 on a small program and on Linux 64. On Linux with 1.29 and with a cargo update, it compiles & runs correctly, but on Windows it won't even compile.

Cargo.toml dependencies:

[dependencies]
regex = "0.2"
rand = "0.4"
lazy_static = "1.0"

external crates:

#[macro_use]
extern crate lazy_static;
extern crate rand;
extern crate regex;

Errors (line-wrapped):

R:\rs\wordladder>cargo build --release --
   Compiling version_check v0.1.4
   Compiling libc v0.2.43
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `libc`.
warning: build failed, waiting for other jobs to finish...
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `version_check`.

To learn more, run the command again with --verbose.

R:\rs\wordladder>cargo build --release --verbose
   Compiling version_check v0.1.4
   Compiling libc v0.2.43
     Running `rustc --crate-name version_check
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823\version_check-0.
1.4\src\lib.rs --crate-type lib --emit=dep-info,link -C opt-level=3
-C codegen-units=1 -C metadata=b1ee3c6bf1cabb43 -C extra-
filename=-b1ee3c6bf1cabb43 --out-dir
R:\rs\wordladder\target\release\deps -L
dependency=R:\rs\wordladder\target\release\deps --cap-lints allow
-Ctarget-feature=+crt-static`
     Running `rustc --crate-name libc
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823\libc-0.2.43\src\lib.rs
-- crate-type lib --emit=dep-info,link -C opt-level=3 -C
codegen-units=1 --cfg "feature=\"default\"" --cfg
"feature=\"use_std\"" -C metadata=b514e7d56015e14b -C
extra-filename=-b514e7d56015e14b --out-dir
R:\rs\wordladder\target\release\deps -L dependenc
y=R:\rs\wordladder\target\release\deps --cap-lints allow
-Ctarget-feature=+crt-static`
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `libc`.

Caused by:
  process didn't exit successfully: `rustc --crate-name libc
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db9ec823\li
bc-0.2.43\src\lib.rs --crate-type lib --emit=dep-info,link -C
opt-level=3 -C codegen-units=1 --cfg "feature=\"default\"" --cf g
"feature=\"use_std\"" -C metadata=b514e7d56015e14b -C
extra-filename=-b514e7d56015e14b --out-dir R:\rs\wordladder\target\re
lease\deps -L dependency=R:\rs\wordladder\target\release\deps
--cap-lints allow -Ctarget-feature=+crt-static` (exit code: 1)
warning: build failed, waiting for other jobs to finish...
LLVM ERROR: IO failure on output stream: bad file descriptor
error: Could not compile `version_check`.

Caused by:
  process didn't exit successfully: `rustc --crate-name version_check
C:\Users\mark\.cargo\registry\src\github.com-1ecc6299db
9ec823\version_check-0.1.4\src\lib.rs --crate-type lib
--emit=dep-info,link -C opt-level=3 -C codegen-units=1 -C metadata=b1e
e3c6bf1cabb43 -C extra-filename=-b1ee3c6bf1cabb43 --out-dir
R:\rs\wordladder\target\release\deps -L dependency=R:\rs\wordladd
er\target\release\deps --cap-lints allow -Ctarget-feature=+crt-static`
(exit code: 1)

I can share the Cargo.toml and src/main.rs if that will help: the program should build on both Linux and Windows, but will only run on Linux unless you change a line that loads in a words file.

I'm no Windows expert, but I just tried a minimal project on Windows 10 x86_64-pc-windows-msvc with those dependencies, and it built fine. If you can share your project, I'll give it a shot.

I notice you're building in R:\ -- is that something odd like a network drive?

Not really at the moment. The big ones are:

  • 1.30: proc macros
  • 1.31: rust 2018
3 Likes

NLL is not stable yet. It has a few days more of FCP. That means 1.31 for it.

If you have something like Vec<Vec<T>>, you can iterate all items with vec.iter().flatten().

I've also had cases where I want to filter out some iterable items before I flatten them, and that's hard to do with a single flat_map if there's not an easy empty type too. So I end up with a .filter(...).flat_map(|x| x), which is now the same as .filter(...).flatten().

3 Likes

Nice release, looking forward to 1.30 which will stabilise proc-macro's. Also looking forward to better Clippy and Rustfix integrations in the future.

Is it a bug or oversight that the release notes mention:

Additionally, you can now compare &str and OsString .

(which is confirmed by the tag on the relevant commit)

Yet the annotation seems to mark them as stable since 1.28:

You're right -- this was also reported in #54195. I opened PR54203 to fix it.

1 Like

I'm wondering how to effectively use cargo fix. In my experience it pays to manually examine every warning rustc throws for more often than not it is pointing to an actual bug in your code. For example when it's talking about an unusused variable more likely than you needing to prepend an _ you need to actually use that variable in your logic somewhere. This very situation has happened with me so many times and saved my skin. With cargo fix wouldn't people develop a detrimental reflex of simply running the tool as soon as they see warnings? Do you guys see that as a real risk from usability point of view?

1 Like

Whoa, I did not know that and feel lucky that I haven't been bitten by that before. Thanks for pointing that out.

The release blog states that cargo fix will only change code when it can be certain it can actually fix it in some satisfactory way.
So to take the unused binding example, it would change an unused binding foo to either _foo or _ (there is a semantic difference between the 2, and I believe the former is chosen).

R:\ is a virtualbox drive visible to Windows but actually a Linux dir.

Discourse only allows me to upload images, so here are the two files:

Cargo.toml

[package]
name = "wordladder"
version = "0.1.0"
authors = ["Mark"]

[profile.release]
codegen-units = 1

[dependencies]
regex = "0.2"
rand = "0.4"
lazy_static = "1.0"

src/main.rs:

#[macro_use]
extern crate lazy_static;
extern crate rand;
extern crate regex;

use std::fs::File;
use std::io;
use std::io::{BufReader,BufRead};
use std::collections::HashSet;
use std::time::{Duration, Instant};
use regex::Regex;

static WORDFILE: &str = "/usr/share/hunspell/en_GB.dic";
const SIZE: usize = 4; // Should be even
const STEPS: usize = SIZE;

type WordSet = HashSet<String>;
type WordVec = Vec<String>;
type Letters = Vec<char>;

fn main() {
    if let Ok(words) = read_words(WORDFILE, SIZE) {
        let timer = Instant::now();
        let mut count = 1;
        print!("Try ");
        loop {
            print!(".");
            if let Some(ladder) = generate_ladder(&words, STEPS) {
                println!("{}", count);
                for word in ladder {
                    println!("{}", word);
                }
                break;
            }
            count += 1
        }
        println!("{:.05} sec", as_secs(timer.elapsed()));
    }
}

fn as_secs(duration: Duration) -> f64 {
    duration.as_secs() as f64 + duration.subsec_nanos() as f64 * 1e-9
}

fn generate_ladder(words: &WordSet, steps: usize) -> Option<WordVec> {
    let mut words = words.clone();
    let compatibles = words.clone();
    let mut ladder = vec![];
    let mut prev = update_words_and_ladder(&mut ladder, &mut words,
                                           &compatibles);
    for _ in 0..steps + 1 {
        let compatibles = compatible_words(prev.as_str(), &words);
        if compatibles.is_empty() {
            return None
        }
        prev = update_words_and_ladder(&mut ladder, &mut words,
                                       &compatibles);
    }
    let first: Letters = ladder[0].chars().collect();
    let last: Letters = ladder[ladder.len() - 1].chars().collect();
    for i in 0..first.len() {
        if first[i] == last[i] {
            return None // Don't accept any vertical letters in common
        }
    }
    Some(ladder)
}

fn update_words_and_ladder(ladder: &mut WordVec, words: &mut WordSet,
                           compatibles: &WordSet) -> String {
    let mut rng = rand::thread_rng();
    let prev = rand::seq::sample_iter(&mut rng, compatibles, 1)
        .unwrap()[0];
    ladder.push(prev.to_string());
    words.remove(prev);
    prev.to_string()
}

fn compatible_words(prev: &str, words: &WordSet) -> WordSet {
    let mut compatibles = WordSet::new();
    let prev_chars: Letters = prev.chars().collect();
    let size = prev_chars.len() - 1;
    for word in words.iter() {
        let mut count = 0;
        let word_chars: Letters = word.chars().collect();
        for i in 0..prev_chars.len() {
            if prev_chars[i] == word_chars[i] {
                count += 1;
            }
        }
        if count == size {
            compatibles.insert(word.to_string());
        }
    }
    compatibles
}

fn read_words(wordfile: &str, size: usize) -> io::Result<WordSet> {
    lazy_static! { static ref RE: Regex = Regex::new(r"^[a-z]+").unwrap(); }
    let mut words = WordSet::new();
    let file = File::open(wordfile)?;
    for line in BufReader::new(file).lines() {
        if let Ok(line) = line {
            if let Some(captures) = RE.captures(&line) {
                let word = &captures[0];
                if word.len() == size {
                    words.insert(word.to_uppercase());
                }
            }
        }
    }
    Ok(words)
}

As noted this compiles and runs fine with 1.28 on Windows and Linux even after doing a cargo update. But with 1.29 it only works on Linux. However, taking your hint, I tried it on C: and it worked fine.

So it looks like the problem is with the virtualbox drive (which I guess looks like a network shared drive to Windows). This is a pain for me because I do all my editing on Linux and only use Windows for compiling and testing but will have to always have to copy to C: to do this now: unless it gets fixed of course. So, for now, I'll hold off on 1.29 and hope that this is fixed. (I'll add an issue about it: #54216.)