Rust reference is never null?

I read that Rust reference is never null but this compiles

fn main() {

    let x: &i32;

}

So is x initialized to something?

x won't be initialized to anything, but Rust will prevent you from doing anything with the variable until you do initialize it (see this relevant section of the Rustinomicon). The only way you'd be able to get a null reference from x would be using unsafe code.

Also, in your current example, since you don't assign or read x, the compiler will probably just optimize it away.

5 Likes

I'm curious why Rust do not disallow this and enforce compulsory initialization let x: &i32 = &10 for example

Variables can be initialised later on. As for forbidding variables that are declared but never initialised or used... could have a lint for it, but it's not like they can hurt anything.

2 Likes

Can you explain why you think it should be disallowed, given that Rust already won't compile a program that tries to read an uninitialized variable?

1 Like

Hello!

As others pointed out, it's an harmless declaration so why prevent it?

Anyhow, the compiler warns you about the useless declaration, and encourages you to rename (or remove, I'd say) it.

warning: unused variable: `x`
 --> src/main.rs:3:9
  |
3 |     let x: &i32;
  |         ^ help: consider using `_x` instead
  |
  = note: #[warn(unused_variables)] on by default
1 Like

The "builder pattern" is a common multi-step pattern for initializing a struct, including where there are internal consistency requirements among the struct's fields. In such cases deferred initialization of some of those fields may be a logical necessity.

3 Likes

As a newbie to Rust seeing let x: &i32; gives me the impression that Rust by default initializes it to some default value. For example in Java boolean type will default to false

Well, it doesn't, and if you tried to use x, you'd get a hard error. You can't really have the wrong idea about this for very long. :stuck_out_tongue:

8 Likes

Another point is if it was disallowed IDE will be able to prompt the mistake even before attempting to compile. Currently we have to wait until compilation stage to know what's wrong. E.g. using an uninitialized variable.

If your IDE is worth anything, it'll run cargo check or similar over the code in the background and show the compilation errors and warnings. One of these warnings is "x is unused".

2 Likes

As a matter of scoping convenience, this construction is useful.

let x;
if foo() {
    x = 1;
} else {
    x = 2;
}

Rust uses expression ifs so you could do this with such a trivial example:

let x = if foo() {
  1
} else {
  2
};

But there could be more complex conditionals where you would want to do it more in the former style.

11 Likes

Point taken, i am using Intellij, seems like there is a lot of things it is not picking up.

1 Like

The first reply in this thread, from 17cupsofcoffee, recommended reading a section of the Rustnomicon (reference in that post) which explains about the Rust compiler's tracking of whether variables and subfields are initialized. In most cases this enables compile-time error detection with no run-time overhead, in line with Rust's general approach to error detection without overhead.

1 Like

I think you hit the nail on the head: the compiler prevents me from doing stupid things. So, IMHO, all is good.

1 Like

Go to Settings > Languages and Frameworks > Rust (that's where it is in CLion at least) and check "Use cargo check to analyze code." This option doesn't miss anything because it is the compiler! :wink:

5 Likes

Thanks man. Awesome tip. Now i am wondering why intellij didn't enable by default. :smile:

4 Likes

I suspect it has something to do with the fact that, once somebody discovers the feature, they hardly have any reason to use (and report bugs in) the plugin's built-in analyses :stuck_out_tongue:

1 Like