Introducing a new Symbol in a Match Arm?

I apologize for presenting this in an IDE-centric way, but I am shocked to find that when I am matching on &str arms, and I include a symbol as one of the arms that is not in scope, instead of a compilation error, Rust compiles and treats that arm as the 'catch all arm'.

For example, given this complete program:

pub const SOMETHING: &str = "something";
pub const SOMETHING_ELSE: &str = "somethingElse";

fn main() {
    let x = "something";
    match x {
        SOMETHING => {},
        SOMETHING_ELSE => {},
        BOGUS_SYMBOL => {},
        _ => {}
    }
}

I'm surprised that it compiles with a warning unused variable: BOGUS_SYMBOL.

What is going on here. This is not the desired behavior as far as I'm concerned! This is especially bad when trying to quickly refactor, move things around etc, when compilations have a million warnings until you clean things up... instead of following compiler errors around and fixing, I can actually get a baffling program instead!

and a warning variable `BOGUS_SYMBOL` should have a snake case name

you could #![deny(non_snake_case)]

Edit: you also get unreachable pattern warning. This is something else that you could reasonably turn into an error in your project.

you could #![deny(non_snake_case)]

Right, but to be clear, what I expect is something like

error[E0425]: cannot find value `BOGUS_SYMBOL` in this scope

I guess what you suggest could be used as a workaround to cause a failure. But I still wonder what is happening.

the problem is that something like this works:

pub const SOMETHING: &str = "something";
pub const SOMETHING_ELSE: &str = "somethingElse";

fn main() {
    let x = "something";
    match x {
        y => println!("{}", y)
    }
}

the problem is that something like this works:

Oh I think I understand. If you want to grab the value in the catch-all arm, then you introduce a naked symbol to do so. Too bad!

There is a warnings group nonstandard-style that you might want to deny entirely. It includes the warnings non-camel-case-types, non-snake-case, non-upper-case-globals.

Iā€™m currently trying to find out if you can specify something like this in the Cargo.toml.

There is a warnings group nonstandard-style that you might want to deny entirely. It includes the warnings non-camel-case-types , non-snake-case , non-upper-case-globals .

These errors are good solutions and I will use them.

The reason that I am still very sad, and for which nothing can be done, is that my IDE cannot automatically import symbols in this case.

I use JetBrains and fly through missing imports (in all languages) with a quick option-enter->import on everything that turns red. Can't do it in this case because of language design.

I'm sure that design aspect of the syntax was done way before such considerations came about. It's too bad in retrospect that it doesn't look like this instead

pub const SOMETHING: &str = "something";
pub const SOMETHING_ELSE: &str = "somethingElse";

fn main() {
    let x = "something";
    match x {
        SOMETHING => {},
        SOMETHING_ELSE => {},
        _(unknown_string) => {}
    }
}

You can also do

pub const SOMETHING: &str = "something";
pub const SOMETHING_ELSE: &str = "somethingElse";

mod m {
    pub const BOGUS_SYMBOL: &str = "bogus";
}

// uncomment to make it compile:
// use m::*;

fn main() {
    let x = "something";
    match x {
        self::SOMETHING => {},
        self::SOMETHING_ELSE => {},
        self::BOGUS_SYMBOL => {},
        _ => {}
    }
}

Which probably works better with the IDE and even has rustc suggest the import.

3 Likes

Nice!