Stream: t-compiler/const-eval

Topic: `Vec::new` in array repeat expressions


centril (Oct 23 2019 at 21:02, on Zulip):

So the motivational text of the RFC might not be fully up to date; const X: Vec<T> = Vec::new(); and such may be required but I think we will need to reconsider the design of the RFC

ecstatic-morse (Oct 23 2019 at 21:04, on Zulip):

FWIW I don't think it's a deal-breaker to promote Drop things in an explicit context (this does not include &NeedsDrop)

RalfJ (Nov 03 2019 at 13:01, on Zulip):

I'd rather push towards explicit anonymous const as opposed to promoting more things

RalfJ (Nov 03 2019 at 13:01, on Zulip):

long-term I'd really like is to push towards removing #[rustc_promotable] from as many methods as we can get away with

RalfJ (Nov 03 2019 at 13:01, on Zulip):

probably some of them only had it for backcompat but are hardly used? what would be the requirements for making a fn no longer promoted?

ecstatic-morse (Nov 03 2019 at 19:11, on Zulip):

I agree that rustc_promotable isn't the right thing to do here.

ecstatic-morse (Nov 03 2019 at 19:12, on Zulip):

I may write up an RFC discussing the various ways we could do this.

ecstatic-morse (Nov 03 2019 at 19:16, on Zulip):

We really want to just call Vec::new() N times, not once and have another unstable effect system that determines whether the result of a function call is bitwise copyable.

ecstatic-morse (Nov 03 2019 at 19:19, on Zulip):

But this diverges from the behavior for Copy types, where the initializer is invoked exactly once and then copied N times.

RalfJ (Nov 03 2019 at 19:50, on Zulip):

Vec::new is a const fn so copying is fine -- we should just be explicit about it

ecstatic-morse (Nov 03 2019 at 19:54, on Zulip):

It's not fine if heap allocations ever become const

RalfJ (Nov 03 2019 at 19:55, on Zulip):

Vec::new doesnt do any heap allocation

ecstatic-morse (Nov 03 2019 at 19:57, on Zulip):

Obviously, but we can't differentiate between Vec::new() and Box::new(1i32) (if the latter ever were to become a const fn) without an explicit attribute (e.g. rustc_promotable) or an analysis that looks through function calls

ecstatic-morse (Nov 03 2019 at 19:57, on Zulip):

neither of which we want I think

RalfJ (Nov 03 2019 at 19:58, on Zulip):

solving that problem is the burden of the const-heap-alloc proposal though. it has nothing to do with array init.

RalfJ (Nov 03 2019 at 19:59, on Zulip):

like, a const FOO: Vec<i32> = Vec::new() also relies on this being bit-copyable

RalfJ (Nov 03 2019 at 19:59, on Zulip):

that's what const is about

ecstatic-morse (Nov 03 2019 at 20:04, on Zulip):

I don'twant to make any decisions here that would make const-heap-alloc more difficult is all. If we start guaranteeing bitwise copies for const, how will we ever support const X = Box::new(1)?

ecstatic-morse (Nov 03 2019 at 20:05, on Zulip):

I mean, maybe that ship has already sailed

RalfJ (Nov 03 2019 at 20:56, on Zulip):

I mean, maybe that ship has already sailed

it definitely has

RalfJ (Nov 03 2019 at 20:56, on Zulip):

bit-wise copy is the defining property of const

ecstatic-morse (Nov 03 2019 at 20:58, on Zulip):

it definitely has

I don't think everyone is convinced of this: https://github.com/rust-rfcs/const-eval/issues/20#issuecomment-520227200

ecstatic-morse (Nov 03 2019 at 20:59, on Zulip):

bit-wise copy is the defining property of const

I thought the defining property of const was something like "behaves as if you copy-pasted the definition everywhere the const was used"

ecstatic-morse (Nov 03 2019 at 21:00, on Zulip):

@RalfJ It's possible that this has evolved over time I guess.

RalfJ (Nov 03 2019 at 21:00, on Zulip):

I don't think everyone is convinced of this: https://github.com/rust-rfcs/const-eval/issues/20#issuecomment-520227200

well if they find a way for that the same thing will work for arrays

RalfJ (Nov 03 2019 at 21:00, on Zulip):

bit-wise copy is the defining property of const

I thought the defining property of const was something like "behaves as if you copy-pasted the definition everywhere the const was used"

right, but the "as-if" part would be boring if we really would do that^^

RalfJ (Nov 03 2019 at 21:00, on Zulip):

it's "as-if" because in reality we are just copying the result

RalfJ (Nov 03 2019 at 21:01, on Zulip):

if we change that (and I strongly doubt we will), whatever we do for const uses then is something we can also do for arrays

ecstatic-morse (Nov 03 2019 at 21:05, on Zulip):

Stepping back for a moment, what do you think about the following:

If the type of a repeat array initializer ([expr; 20]) is not Copy, but is explicitly promotable, the array initializer will be expanded to the following array literal ([expr, expr, ..., expr])

ecstatic-morse (Nov 03 2019 at 21:07, on Zulip):

@RalfJ this is the proposal I was considering for the hypothetical RFC I mentioned above.

ecstatic-morse (Nov 03 2019 at 21:09, on Zulip):

I don't like that it does very different things for const-safe initalizers and Copy initializers.

ecstatic-morse (Nov 03 2019 at 21:10, on Zulip):

The reasoning behind this is that it shouldn't be observable whether a const fn is called once with the same inputs or multiple times. I'm not sure how true this is today, and I think a moderately powerful unconst would break this assumption.

ecstatic-morse (Nov 03 2019 at 21:12, on Zulip):

If one of the invocations of expr panics btw, it would be a compile-time error. I assume the reason we don't just do this for every array initializer is we would need to handle panics with a partially initialized array.

RalfJ (Nov 03 2019 at 21:13, on Zulip):

The reasoning behind this is that it shouldn't be observable whether a const fn is called once with the same inputs or multiple times. I'm not sure how true this is today, and I think a moderately powerful unconst would break this assumption.

it is true today but will likely not be true for unsafe code forever

RalfJ (Nov 03 2019 at 21:13, on Zulip):

and UB should be something that you can actually check, which "impurity" isn't, not really

RalfJ (Nov 03 2019 at 21:14, on Zulip):

do you know what the plans are (if any) for "truly run-time" array initializers? @Centril mentioned something along those lines

ecstatic-morse (Nov 03 2019 at 21:17, on Zulip):

No idea, although that would make this a non-issue. The only concern I have is that it would behave very differently Copy types than for non-Copy ones when the initializer has side effects: [rand::<BigInt>(); 4] vs [rand::<i32>::(); 4]

ecstatic-morse (Nov 03 2019 at 21:18, on Zulip):

One thing that someone brought up at the lang-team meeting was making the requirement const Clone instead of Copy

ecstatic-morse (Nov 03 2019 at 21:18, on Zulip):

Obviously this depends on having support for const traits

ecstatic-morse (Nov 03 2019 at 21:18, on Zulip):

so it's a ways off

ecstatic-morse (Nov 03 2019 at 21:19, on Zulip):

But it would mean that any observable side-effects would have to be in the Clone impl, which we could more easily make rules around.

RalfJ (Nov 03 2019 at 21:20, on Zulip):

hm. but that would likely also require us to actually evaluate clone N times

RalfJ (Nov 03 2019 at 21:21, on Zulip):

[const { Vec::new() }; N], using anonymous constant, seems like the easiest way forward IMO

ecstatic-morse (Nov 03 2019 at 21:27, on Zulip):

I don't think that really resolves the question about whether that means called N times, called once and const-cloned N times, or called once and bitwise copied N times (the final one requiring that the top-level value in a const be bitwise-copyable)

RalfJ (Nov 03 2019 at 21:44, on Zulip):

if you tie this to const Clone then of course this ties it to const-clone it N times, how else would it make any sense?

ecstatic-morse (Nov 03 2019 at 21:45, on Zulip):

There's three choices above

ecstatic-morse (Nov 03 2019 at 21:45, on Zulip):

That's one of them

ecstatic-morse (Nov 03 2019 at 21:46, on Zulip):

The proposal I described would be the first (expr would be evaluated N times)

ecstatic-morse (Nov 03 2019 at 21:47, on Zulip):

I assume that you're in favor of the last one (expr evaluated once and bitwise-copied N times)

RalfJ (Nov 05 2019 at 09:26, on Zulip):

The proposal I described would be the first (expr would be evaluated N times)

what I ams aying is, if this is what we do, what's the point of the const Clone requirement?
I guess I am just confused at what concretely you are proposing.

ecstatic-morse (Nov 05 2019 at 16:55, on Zulip):

The const Clone idea is mutually exclusive with the first one. It would be more consistent with the current behavior of array initialization for non-const functions that return Copy types (called once, copied N times)

RalfJ (Nov 05 2019 at 19:23, on Zulip):

I think I got confused between the multiple ideas that you raised and about what belonged to what^^

ecstatic-morse (Nov 05 2019 at 19:24, on Zulip):

I could have been more clear.

ecstatic-morse (Nov 05 2019 at 19:25, on Zulip):

I'm just thinking out-loud mostly

ecstatic-morse (Nov 07 2019 at 20:33, on Zulip):

@nikomatsakis brought up an interesting point in the lang team meeting today about allowing arbitrary const fns. Currently, we look to see if the initializer is promotable, and if so we run it at compile-time even if it would be allowed at run-time because it is Copy. As a result, making an existing fn that returns a Copy type into a const fn will change the semantics of [fn_that_might_panic(); 4]. This is the whole reason that we have the implicit/explicit distinction, and it suggests we should use the implicit promotability rules, which don't allow calls to arbitrary const fn.

In the meeting, I proposed only trying to do promotion if the type is not Copy to avoid this problem. Promotion happens pretty late in the compilation pipeline, so this is probably feasible, but there's complexity around e.g. generics/associated consts. I don't think this feature warrants the additional complexity, so I'm inclined to use the rules for implicit promotion.

oli (Nov 08 2019 at 11:19, on Zulip):

yes

oli (Nov 08 2019 at 11:19, on Zulip):

we can allow function calls via explicit const blocks

oli (Nov 08 2019 at 11:20, on Zulip):

or we have something like the suggested const(heap) functions which are const(dont_panic)

ecstatic-morse (Nov 08 2019 at 13:37, on Zulip):

ATM, rustc_promotable is basically dont_panic right?

oli (Nov 08 2019 at 13:38, on Zulip):

nope

oli (Nov 08 2019 at 13:38, on Zulip):

&(0 - 7) gets promoted

ecstatic-morse (Nov 08 2019 at 13:39, on Zulip):

I mean the attribute. Would you ever put it on a function that panicked?

ecstatic-morse (Nov 08 2019 at 13:40, on Zulip):

Is it promising more?

ecstatic-morse (Nov 08 2019 at 14:00, on Zulip):

I mean#[rustc_promotable] doesn't actually check anything in the function body, but I think that's pretty much how it's used.

oli (Nov 08 2019 at 16:26, on Zulip):

oh... yea, that's kinda true

oli (Nov 08 2019 at 16:27, on Zulip):

I thought you meant an analysis

RalfJ (Nov 09 2019 at 11:08, on Zulip):

Currently, we look to see if the initializer is promotable, and if so we run it at compile-time even if it would be allowed at run-time because it is Copy.

Some weeks ago I specifically asked if we do that because it would be problematic -- failure to promote must imply failure to compile (if we use explicit promotion rules), and this is a counterexample. Back then I was told that indeed we only fall back to promotion but prefer Copy, so now I am confused^^

RalfJ (Nov 09 2019 at 11:10, on Zulip):

so I feel I raised that exact point weeks ago^^ I am glad that it now got recognized but I am worried why it needs to be raised multiple times for that to happen.

RalfJ (Nov 09 2019 at 11:10, on Zulip):

&(0 - 7) gets promoted

the thing that gets promoted doesnt panic though

RalfJ (Nov 09 2019 at 11:10, on Zulip):

we promote the overflowing_add, which is dont_panic

ecstatic-morse (Nov 11 2019 at 00:27, on Zulip):

@RalfJ the change in my thinking was around the second paragraph, not the first. I used to think the fact that we did promotion unconditionally was a bug that should be fixed. I now no longer think this. You can watch the lang-team meeting video (should be around minute 5) once it's posted to see the discussion in full.

ecstatic-morse (Nov 11 2019 at 00:28, on Zulip):

If your concerns are about me specifically, perhaps we should discuss them in private.

Last update: Nov 15 2019 at 20:40UTC