Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I annotate rust variables' data type without assignment?

I'm new to rust, and I'd like to declare a typed variable without initializing it. Is this possible in Rust? If so, is it advisable or are there better, more rustacean-y ways to do it?

I'm looking at the following code from rustlings which fails to compile because it can't infer the type of x:

    let x;
    if x == 10 {
        println!("Ten!");
    }

So, I tried this:

let x: i32;

however, now the compiler will throw an error on the comparison line saying that x hadn't been declared.

This works fine, but I was left wondering if one can declare the type without an assignment.

let x: i32 = 10;

Or is the correct way to do it involve designing your code to avoid such situations in the first place? I come from a C background and I'm probably a little too comfortable with being lazy with types.

like image 383
TopherIsSwell Avatar asked Jan 27 '26 02:01

TopherIsSwell


1 Answers

In rust, the type of a variable is usually inferred from the context.
The context can include any of the following:

  • The type of the value being assigned:
let x = String::new(); //x is now a String
  • The return type of the function being called:
fn foo() -> usize {
    40
}
let x = foo(); //x is now usize

But if you don't have a type to infer, as in there is no assignment to the variable:

let x;

Then rust cannot infer the type. Therefore, it will get mad at you.

Another problem that needs to be addressed in this answer; the fact that rust doesn't allow the reading of uninitialized variables. The following value, x is uninitialized:

let x: u32;

Reading the value of an uninitialized u32 probably wouldn't do too much, but consider the following:

struct MyString {
    ptr: *const u8,
    len: usize,
    cap: usize,
}

If we were to provide a safe wrapper around this, this would be perfectly fine, after all, this is essentially what the stdlib String boils down to. But, if we were to own an uninitialized MyString and tried to read its contents, we'd end up reading a garbage address from the ptr, and a garbage len and cap. This would lead to reading a garbage pointer, which is undefined behavior, which is rust's #1 priority to eliminate.

So, to recap:
✓ Every variable must have a type determinable at runtime (Including erased types, because those are concrete types too [dyn Trait and impl Trait], but impl Trait is special.)
✓ Every variable must be assigned some kind of value before you can read its value.
✓ Rust tries very hard to eliminate all undefined behavior.

like image 170
Optimistic Peach Avatar answered Jan 29 '26 04:01

Optimistic Peach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!