MAG
MAG

Reputation: 474

Is 'mem::size_of' evaluated at compile time?

When using this expression:

mem::size_of::<T>() * 8

Like this:

value % (mem::size_of::<T>() * 8);
value * (mem::size_of::<T>() * 8);

would the compiler be able to optimize it to this:

value & ((mem::size_of::<T>() * 8) - 1);
value >> LOG2_OF_EXPRESION;

Is there something equivalent to C++'s constexpr so I can return it from a function and use it where a compile time expression would be expected?

Upvotes: 3

Views: 773

Answers (1)

Shepmaster
Shepmaster

Reputation: 431589

As of Rust 1.22.0

mem::size_of is now declared as a const fn, which means that it is guaranteed to be able to be evaluated at compile time. You can make use of it in const contexts:

use std::mem;

const BYTES: usize = mem::size_of::<f64>();

fn main() {}

Prior to Rust 1.22.0

The only way to know for sure is to look at the LLVM IR or assembly. It is allowed for this to change over time, so if it's super important, you need to keep track of it yourself.

As of Rust 1.14, this code:

#![crate_type="lib"]

use std::mem;

pub fn use_it() -> usize {
    mem::size_of::<String>() * 8
}

produces this LLVM IR when compiled in debug mode:

; Function Attrs: norecurse nounwind readnone uwtable
define i64 @_ZN10playground6use_it17h005e773511657405E() unnamed_addr #0 {
entry-block:
  ret i64 192
}

As you can see, the call to size_of has become the constant value 192. Rust and/or LLVM are then able to do whatever normal optimization they want to.

I'd believe it is safe to assume that this function will always be a compile-time constant.

Is there something equivalent to C++'s constexpr

See Equivalent of constexpr from C++?

Not yet. RFC 911 introduced const functions, functions which are able to be evaluated at compile time. The trick is that actually enabling this for everything that it should work with is difficult and predicated on some internal rewriting of the compiler.

In nightly Rust, you can do something like:

#![feature(const_fn)]

const fn adder(a: usize, b: usize) -> usize {
    a + b
}

const BITS: usize = adder(1, 2);

fn main() {
    println!("{}", BITS);
}

Upvotes: 7

Related Questions