What is the reason behind RFC 2920 (inline const expressions)

Link to the RFC

I'd like to understand better the motivation behind inline const expressions, in particular its intersection with const fn.

From what I understand, inline const expressions allow to execute the context of the block at compile time. While, const fn enables to call free function in a constant context, and therefore also allows to evaluate the context at compile time.

Now taking into consideration the 2 examples from the RFC.

The first example:

fn foo() -> &'static i32 {
    &const { 
        let x = 4i32;
        x.pow(5)
    }
}

Assuming pow can be evaluated at compile time, I should be able to write an equivalent version using const fn:

#![feature(const_fn)]
#![feature(const_int_pow)]

const fn foo(x: i32) -> i32 {
    x.pow(2)
}

But if I try to return a 'static reference I get:

const fn foo(x: i32) -> &'static i32 {
    &x.pow(2)
}
error[E0515]: cannot return reference to temporary value
 --> src/main.rs:5:5
  |
5 |     &x.pow(2)
  |     ^--------
  |     ||
  |     |temporary value created here
  |     returns a reference to data owned by the current function

even thogh, if this was possible with the inline const version, then it should be in theory also possible with the const fn version, and if that is the case (compilers are not my field of expertise so I may be completely wrong), the const fn version achieves the same result by being much less verbose.

Regarding the second example:

fn main() {
    match *x {
        0 ..= const { u32::MAX / 2 } => println!("low"),
        const { u32::MAX / 2 + 1 } ..= u32::MAX => println!("high"),
    }
}

What makes me wonder is the need for const { u32::MAX / 2 + 1 }, since I would assume that by default, when dealing with const and litterals, the compiler should be able to evaluate the expression at compile time by default, without the need for a const inline block.

Are my assumption and/or my conclusions wrong? What is the need for const inline expression if compile time evaluation could be in theory be achieved via const fn?

You can call const fns at runtime. They aren't guaranteed to run at compile time except when you use them in a const context (for instance, to initialize a static).

fn main() {
    for (x, _) in std::env::args().enumerate() {
        let rx = foo(x as u32);  // wait, does this return a 'static reference? To what?
    }
}

Inline const provides a const context, which calling a const fn does not do.

1 Like

Thanks for your reply. My point focuses more on the actual need to make the context explicitly const rather than the static lifetime.

Where, if we are in a const context const fn can/should be evaluated as complile time -> const inline expression is not required.

If the context is not const (like in your example) neither const fn nor const inline blocks can effectively compute the value at compile time (and no 'static lifetime can be returned from foo).