Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

const_eval: Consider array length constant even if array is not #99594

Closed
wants to merge 1 commit into from

Conversation

TheWastl
Copy link
Contributor

Fixes #98444.

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jul 22, 2022
@rustbot
Copy link
Collaborator

rustbot commented Jul 22, 2022

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

@rust-highfive
Copy link
Collaborator

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 22, 2022
@leonardo-m
Copy link

So is this reasonable code now allowed?

fn main() {
    let a = [1_u32, 2, 3];
    let b = [0; a.len()];
}

@TheWastl
Copy link
Contributor Author

So is this reasonable code now allowed?

fn main() {
    let a = [1_u32, 2, 3];
    let b = [0; a.len()];
}

No, this PR should only affect constant propagation for the purposes of optimization and lints. (Ok, maybe the title is a bit misleading.)

In particular, your code already fails a step earlier: accessing a is forbidden, regardless of what you do with it. For instance, this fails, too:

fn main() {
    let a = [1_u32, 2, 3];
    let b = [0; { a; 3 }];
}

let mplace = self.force_allocation(&src)?;
let len = mplace.len(self)?;
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
if let &ty::Array(_, len) = src.layout.ty.kind() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. It is certainly not right without extensive comments explaining what is happening and why the old code is wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a fast path that does the right thing (codegen does this opt after all or mir opts do it for codegen).

I wonder if this has any effect on miri at all (the force alloc will just happen later?). If there is no benefit to miri, we should just teach const prop about the Len Rvalue

Copy link
Member

@RalfJung RalfJung Jul 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Miri shouldn't usually have fast paths though. We want to catch all the UB, not take any shortcuts. ;)

However, OpTy also has a len method these days, so I think a patch could be made that avoids force_allocation. That sounds like a good idea. I don't know if it helps ConstProp though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Miri shouldn't usually have fast paths though. We want to catch all the UB, not take any shortcuts. ;)

Ok, that makes sense.

However, OpTy also has a len method these days, so I think a patch could be made that avoids force_allocation. That sounds like a good idea. I don't know if it helps ConstProp though.

I did some testing, and using OpTy doesn't seem to help ConstProp.

If there is no benefit to miri, we should just teach const prop about the Len Rvalue.

There's two ConstProps: const_prop and const_prop_lint (since #94934). I guess this should be added to both?

And should I force-push this PR, or open a new one? Changing this one might make the existing discussion a bit confusing for future readers.

(sorry for the delay)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue you want to fix is about the lint, so const_prop_lint is the most relevant one.

I did some testing, and using OpTy doesn't seem to help ConstProp.

Ah, place_to_op will still want to read the local and that is where ConstProp bails.

@RalfJung
Copy link
Member

RalfJung commented Jul 22, 2022

this PR should only affect constant propagation for the purposes of optimization and lints.

Sorry, but I don't think we want to have changes in the interpret folder that only benefit const-prop. The code in that folder is rather important to get right for CTFE and Miri, so if ConstProp needs something weird, it should hack around that on its own terms. ConstProp is already grossly misusing the interpreter, and I am going to object any further technical debt being imposed on the interpreter in the name of ConstProp, except if it is absolutely needed to fix ICEs.

@oli-obk has plans for making ConstProp independent of the interpreter. That is the right way to fix these problems.

@shamatar
Copy link
Contributor

shamatar commented Jul 22, 2022

One may try to change the .len() for arrays to be not just coercion to slice and most likely it will be sufficient

N.B. It may be not the only place where some information (type level constant in array's case) is lost

@@ -251,9 +252,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

Len(place) => {
let src = self.eval_place(place)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to do src.place_to_op(src)?, which will give you a OpTy, and then call len on that. That would avoid force_allocation.

@jackh726
Copy link
Member

jackh726 commented Aug 3, 2022

@RalfJung I'm going to assign you as reviewer here. Feel free to reassign if you can't review

r? @RalfJung

@rust-highfive rust-highfive assigned RalfJung and unassigned jackh726 Aug 3, 2022
@TheWastl
Copy link
Contributor Author

TheWastl commented Aug 5, 2022

Closing in favour of #100160 (wow 6 digits).

@TheWastl TheWastl closed this Aug 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Taking a shared reference of an array suppresses the unconditional_panic lint
8 participants