Skip to content

Instantly share code, notes, and snippets.

@vladak
Last active November 17, 2025 19:05
Show Gist options
  • Select an option

  • Save vladak/f8f7ac1d48e4011e061ee0e06cabaf01 to your computer and use it in GitHub Desktop.

Select an option

Save vladak/f8f7ac1d48e4011e061ee0e06cabaf01 to your computer and use it in GitHub Desktop.
Rust gotchas

Learning Rust gotchas

That is, learning from C99.

Basics

  • by default variables are constant. To make a variable mutable, it has to have the mut keyword:
    • otherwise it would not compile
fn main() {
    // also, type inferrence
    let mut foo = 'A';
    foo = 'b';
}
  • duplicate variable definitions get marked merely as unused variables:
fn main() {
  let foo = 1;
  let foo = 3;
}
  • The exclamation mark means this is a macro.
    • for printing there is also print! and eprint! and eprintln! (for stderr)
fn main() {
    println!("Hello, world!");
}
  • print macros have interpolation:
fn main() {
  let foo = "bar";
  println!("{}", foo);
  println!("{foo}"); // since some Rust version
}
  • the ability to use expressions within the {} seems to be limited (unlike in Python)
fn main() {
    let signs = "QRYZEPTGMk ";
    println!("{signs.len()}"); // fails to compile
    println!("{}", signs.len());
}
  • no semicolon at the end of a function means the value should be returned
fn main() {
    // there does not have to a semicolon for the last expression/statement in a block/function
    let x = println!("{}", 'A'.is_ascii_hexdigit())
}
  • there is 128-bit integer type:
fn main() {
    let mut foo:u128 = 2 << 68;
    while foo > 0 {
        // also, string interpolation
        println!("{foo}");
        foo = foo / 8;
    }
}
  • accessing a slice beyond outside index results in panic (due to the bound check):
fn main() {
    let signs = " TGMK";
    // also note that slice cannot be used directly on str (&signs[8]) cause of UTF-8
    let letter = &signs.as_bytes()[8];
 }
  • sliced str (string type) has to be dereferenced and casted to get a printable char:
fn main() {
    let signs = "TGMK ";
    let letter = &signs.as_bytes()[0];
    println!("letter '{}'", *letter as char);
}

Build

  • rustc is the low-level compiler utility, cargo is the high-level (make/dependencies)

    • cargo run, cargo build, cargo clean
  • there is no macro language per se like in C, however portions of code can be compiled based on flags

# Cargo.toml

[features]
my_feature = []
    #[cfg(feature = "my_feature")]
    {
        println!("count = {count}");
        print!("{foo} ");
    }

target autodiscovery

https://doc.rust-lang.org/cargo/reference/cargo-targets.html#target-auto-discovery

The directory structure allows e.g. for compilation of multiple binaries. src/bin/{foo,bar}.rs will build 2 programs in the target directory after running cargo build.

Used this for my Advent Of Code solutions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment