Skip to content

Latest commit

 

History

History
168 lines (128 loc) · 5.39 KB

File metadata and controls

168 lines (128 loc) · 5.39 KB

Table of Contents

Rust

Undefined behaviors

Floating point to integer casts

fn main() {
    let a = 360.0f32;
    println!("{:?}", a as u8);
    
    let a = 360.0f32 as u8;
    println!("{:?}", a);
    
    println!("{:?}", 360.0f32 as u8);
}

Expected result: 3x the same (despite the u8 overflow)

Results:

104  // this is consistent between runs
208  // this varies on every single run!
255  // this is consistent between runs

Tested with:

  • rustc 1.33.0
  • rustc 1.35.0-nightly

See also: rust-lang/rust#10184

Memory error


Pattern guard consuming value being matched

fn main() {
    let a = Some("...".to_owned());
    let b = match a {
        Some(_) if { drop(a); false } => None,
        x                             => x,
    };
    println!("{:?}", b);
}

Expected result: build error (matched value a is dropped in pattern guard)

Result: builds fine, and prints random values or crashes

Reason:

Tested with:

  • rustc 1.18.0 (03fc9d622 2017-06-06)
  • rustc 1.20.0-nightly (859c3236e 2017-06-26)

See also: rust-lang/rust#31287


Cursed/Weird code

This section contains code that is not inherently wrong, but is quite hard to read, convoluted, or strange in other ways.

Quote each token

Macros can quickly become very hard to read or understand

macro_rules! quote_each_token {
    ($tokens:ident $($tts:tt)*) => {
        $crate::quote_tokens_with_context!{$tokens
            (@ @ @ @ @ @ $($tts)*)
            (@ @ @ @ @ $($tts)* @)
            (@ @ @ @ $($tts)* @ @)
            (@ @ @ $(($tts))* @ @ @)
            (@ @ $($tts)* @ @ @ @)
            (@ $($tts)* @ @ @ @ @)
            ($($tts)* @ @ @ @ @ @)
        }
    };
}

This is real code from the quote crate! The link includes an explanation of how the macro works.

Expected result: uh

Bastion of the Turbofish

This examples comes from tests/ui/parser/bastion-of-the-turbofish.rs in Rust's unit tests:

fn main() {
    let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
    let _: (bool, bool) = (the<guardian, stands>(resolute));
}

Numbers? Nope, we have types!

The definitions of types in crate digest is interesting:

pub type N1152921504606846976 = NInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>>;

This is a definition of a singleton type representing an integer, defined recursively. This is used for type-level programming at compile time.

There other neat definitions in the same file

This cannot be true

This examples comes from tests/ui/weird-exprs.rs in Rust's unit tests:

let val = !((|(..):(_,_),(|__@_|__)|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})//
;

After removing comments, removing code with no action, and executing closures (left as exercise for reader :p), this expands to an equality test let val = !(()==()); which results to false.

More macros

Macros can be defined ... in other macros. This snippet from the uom crate shows an example:

macro_rules! storage_type_types {
    ($($macro_name:ident!($feature:tt, $name:ident, $($type:tt)+);)+) => {
        $(#[macro_export]
        #[doc(hidden)]
        #[cfg(feature = $feature)]
        macro_rules! $macro_name {
            ($attr:tt @$M:ident $tt:tt) => {
                storage_types!(@$M $attr $name, $($type)+; $tt);
            };
        }

        #[macro_export]
        #[doc(hidden)]
        #[cfg(not(feature = $feature))]
        macro_rules! $macro_name {
            ($attr:tt @$M:ident $tt:tt) => {
            };
        })+
    };
}

Full code here