Is this a legacy usage of "ref" keyword?

I know ref keyword is still useful in some situations, for example:

let input = "rust";
let res = input.parse::<i32>();
if let Err(ref x) = res {
    println!("x is: {x}");
}
println!("res is {:?}", res);

This won't be possible without using ref in if let.

But how about this example from Iterator.::inspect() documentation?

let lines = ["1", "2", "a"];

let sum: i32 = lines
    .iter()
    .map(|line| line.parse::<i32>())
    .inspect(|num| {
        if let Err(ref e) = *num { // e is &ParseIntError with or without `ref`
            println!("Parsing error: {e}");
        }
        // this above equals to:
        // if let Err(e) = num {
        //     println!("Parsing error: {e}");
        // }
    })
    .filter_map(Result::ok)
    .sum();

println!("Sum: {sum}");

No. if let Err(x) = &res works.

2 Likes

What's "legacy usage"? ref is not deprecated.

(And it shouldn't be – it's almost always the better option.)

2 Likes

Some sources, like the old version of book and this suggest it. I know it isn't deprecated, but those sources imply ref isn't as needed as it was.

Well, let’s do some research! Googling “rust match ergonomics”, we find the RFC, then the tracking issue from there, and finally, oh! there’s no linked stabilization PR… and wow that’s a lot of “hidden replies” to expand, (load more… load more… load more… load more… ctrl+f… "stabiliz"… previous result… previous… previous) ah here we go, a hint that it’s introduced in Rust 1.26, and the release notes confirm it. (Man that edition-2018 release was insanely overloaded… so many features at once, for no good reason!!)

Anyways, now let’s look at the Iterator::inspect documentation by placing version numbers into the URL… https://doc.rust-lang.org/1.25.0/std/iter/trait.Iterator.html#method.inspect and indeed, it looks like, nope, not a “legacy usage”! …at least in the sense of something being so old that when it was written there was no other way to write it.

Some people may still prefer the old style though, as it’s more explicit about what thing has what type. In particular for inspect which – unlike many other iterator adaptors such as map – provides the items by-reference to the closure, it may well be worth to be as obvious about this fact as possible in the examples, too. (I’ve heard there are many people who like looking mostly only at examples in documentation, anyways.)

Out of curiosity, let’s figure out when the example in question was added, anyways…

Bisecting… 1.30 already present! … 1.27 not there yet! … 1.29 already present! 1.28 present!, so must have been introduced here. So with out 6-week release cycle, these doc were published 12 weeks after stable match ergonomics were released. But also they were written (via contributions to nightly) at a point where the stable match ergonomics were less than 6 weeks old. So perhaps ”legacy” reasons (and/or Rust programmers, especially more experienced ones such as standard library contributors, still being a lot more familiar with the “old” way) still played a role, too, after all.

8 Likes

Although not directly related to the question, but allow me to point out that this is a (somewhat common) fallacy. By the same reasoning, one could say that "match ergonomics" isn't necessary. Both features accomplish (almost) exactly the same thing, so separately, they neither are or aren't necessary, strictly speaking. Either of them would suffice to obtain references in pattern matching.

Match ergonomics was introduced later, but this doesn't automatically mean that it is a superset of, or somehow better than, the older way with refs. There has been considerable bias in the language team around this feature, and it has been pushed through stabilization quickly, forcibly, and inexplicably; despite widespread controversy, and unlike many other, much more trivial features that are still stuck in nightly.

Thus, it is basically inevitable that official sources such as The Book are also biased in favor of match ergonomics and recommend its use, whether it is warranted or not. This is an unfortunate artefact of a derailed governance process, but ref still has objective benefits over match ergonomics. Proponents often claim that it is easier to learn and read, but unfortunately, the converse is true – even during the past couple of weeks, there have been several posts (feel free to search this forum, I can't remember off-hand where they are) by beginners who were confused by being able to match reference-typed values with a non-reference pattern.

So, to sum up:

  • ref is not deprecated;
  • ref is not unnecessary;
  • ref is not useless;
  • ref is not legacy code.
12 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.