How to avoid missing the semicolon which will cause a logic error


#1

This fragment code is from Rust101 tutorial: https://www.ralfj.de/projects/rust-101/part01.html

enum NumberOrNothing {
    Nothing,
    Number(i32),
}

fn vec_min(vec: Vec<i32>) -> NumberOrNothing {
    let mut min = Nothing;
    for e in vec {
        min = Number( match min {
            Nothing => e,
            Number(n) => get_mix(n),
        })**;**
    }
    min
}

For the min assignment statement in the FOR loop, if I miss the “;” in the end by neglect, it will become a legal expression and no any error in syntax, but it is really a logical error. In other language, the compiler will help to warn us, but Rust not. So how to avoid this error, especially in a long function. Thanks in advance.


#2

It behaves exactly the same way whether the semicolon is there or not. There’s no logic error.


#3

In general, I think forgetting a semicolon cannot introduce logic errors. It will in general lead to syntax or type errors at compile time, except for a return type of () (where it is equivalent).


#4

Oops, my mistake, I also just got it by re-read that chapter. Thank you very much again.


#5

Half of me wants to say, yes, I think so too. (I mean, it’s pretty much what I would have posted if notriddle wasn’t such a speedy ninja!)

The other half says: Challenge accepted. :wink:


I can think of an example using the experimental -> impl Trait syntax:

#![feature(conservative_impl_trait)]

// Substitute Debug with e.g. serde::Serialize
// for a slightly more sinister example
use std::fmt::Debug;
fn foo_semi()   -> impl Debug { 3; }
fn foo_nosemi() -> impl Debug { 3  }

fn main() {
    println!("{:?}", foo_semi());
    println!("{:?}", foo_nosemi());
}
()
3

And of course, an existential type can be simulated with a generic callback, so here’s a non-nightly example:

fn bar_semi()   { let x = {3;}; println!("{:?}", x); }
fn bar_nosemi() { let x = {3 }; println!("{:?}", x); }
fn main() { bar_semi(); bar_nosemi(); }

What I’m curious about though is whether there is an example that involves an expression which isn’t at the end of a block; i.e. can removing a semicolon from stmt; stmt; turn it into one big statement with different semantics? Or does the grammar prevent this?

I’m inclined to think it’s the latter, because I don’t think I’ve ever run into such a problem…


#6

That’s a good one, thanks.


#7

If the second statement is a unary negation, removing a semicolon will turn it into binary subtraction.