Stream: t-compiler/const-eval

Topic: stabilize control flow


oli (Mar 14 2020 at 13:08, on Zulip):

Does anything speak against stabilizing panicking, if, match, loop and short circuiting ops? It's been on nightly for a few months, we're using it for libstd stuff already. cc @WG-const-eval

ecstatic-morse (Mar 14 2020 at 19:58, on Zulip):

How comfortable everyone is committing to value-based dataflow analysis, which determines whether e.g. a particular value of Option<Box<T>> has a meaningful destructor, as the engine that powers const-checking? You can imagine a world in which, before let bindings were stabilized in a const context, we only did the value-based analysis for single expressions (e.g., const NULL: Option<Box<T>> = None;). My concern is that we are committing to an implementation that has some compile-time overhead and will be difficult to explain to users (especially once &mut is legal in a const context) without a lot of motivating use cases: the value based analysis allows users to write code such as the following.

const _: () = {
    let x: Option<Box<i32>> = if cond {
        None
    } else {
        None
    };
}
ecstatic-morse (Mar 14 2020 at 20:00, on Zulip):

Is code in that style worth the additional runtime complexity? Or should we just use type-based analysis once a local is assigned multiple times.

bjorn3 (Mar 14 2020 at 20:00, on Zulip):

Did you mean to write None twice?

ecstatic-morse (Mar 14 2020 at 20:01, on Zulip):

@bjorn3 yes

ecstatic-morse (Mar 14 2020 at 20:02, on Zulip):

I can't think of a motivating use case at the moment, but basically the value-based dataflow analysis allows the user to assign to a local multiple times as long as the final assignment on all code paths does not have a meaningful Drop impl.

oli (Mar 14 2020 at 20:30, on Zulip):

While I'm fine with the type based analysis, won't it be confusing for users if some things only work in the trailing expression of a const initializer? We can't regress anything there so we need to keep it around anyway.

oli (Mar 14 2020 at 20:31, on Zulip):

That said, we can always start with a type based version and keep the value based one behind a feature gate

oli (Mar 14 2020 at 20:31, on Zulip):

It's strictly forward compatible

ecstatic-morse (Mar 14 2020 at 20:43, on Zulip):

We allow the code like the following today, so I'm not really sure what a reduced version of the value-based analysis would look like. The "assigned once" rule isn't backwards compatible.

const _: () = {
    let mut x: Option<Box<i32>> = None;
    x = None;
    let y = x;
    y = None;
};
ecstatic-morse (Mar 14 2020 at 20:45, on Zulip):

Performance hasn't been an issue so far, but in a world in which the majority of functions are const fn that may no longer be true.

ecstatic-morse (Mar 14 2020 at 20:49, on Zulip):

ecstatic-morse said:

We allow the code like the following today, so I'm not really sure what a reduced version of the value-based analysis would look like. The "assigned once" rule isn't backwards compatible.

So maybe we have no realistic option besides the status quo, but it's probably good to explore the solution space a bit.

ecstatic-morse (Mar 14 2020 at 20:50, on Zulip):

before stabilizing

oli (Mar 18 2020 at 09:48, on Zulip):

ecstatic-morse said:

Performance hasn't been an issue so far, but in a world in which the majority of functions are const fn that may no longer be true.

We could benchmark this. We can run the const fn analysis without emitting errors on all functions

eddyb (Mar 23 2020 at 15:38, on Zulip):

@ecstatic-morse a more realistic example would choose between multiple variants, none of which need drop or w/e

ecstatic-morse (Mar 26 2020 at 23:52, on Zulip):

oli said:

We could benchmark this. We can run the const fn analysis without emitting errors on all functions

see #70450

Last update: Apr 03 2020 at 18:25UTC