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 evaluating && and || does not short-circuit #29608

Closed
oli-obk opened this issue Nov 5, 2015 · 22 comments
Closed

const evaluating && and || does not short-circuit #29608

oli-obk opened this issue Nov 5, 2015 · 22 comments
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@oli-obk
Copy link
Contributor

oli-obk commented Nov 5, 2015

This prints false

println!("{}", false && ((1u8 - 5u8) == 42));

This gives a compile time error

const X: bool = false && ((1u8 - 5u8) == 42);
println!("{}", X);
@bluss
Copy link
Member

bluss commented Nov 5, 2015

The first has ‘sub with overflow’ as a warning, the second as an error.

@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 5, 2015

yes, but the execution of the first statement (during runtime) works, the execution of the second statement (during compile-time) doesn't.

@steveklabnik
Copy link
Member

/cc @rust-lang/lang is this expected or not?

@nrc
Copy link
Member

nrc commented Nov 11, 2015

I think this is a bug, || and && should have the same semantics in a const as in any other context

@nikomatsakis
Copy link
Contributor

Mmm, I'm not sure. I think this is expected, for the reason @oli-obk states.

@nikomatsakis
Copy link
Contributor

I take it back. I'm not 100% sure what I think.

@nikomatsakis
Copy link
Contributor

Put another way, I think the warning-vs-error thing is a red herring. The question is whether constant evaluation should ever look at the RHS. If it does, then the warning-vs-error is appropriate. That is, if you swapped the order of the arguments to &&, this would be unambiguously the correct behavior.

@nrc
Copy link
Member

nrc commented Nov 11, 2015

Right, I agree warning vs error is ok, but that the rhs should not be evaluated.

@nikomatsakis
Copy link
Contributor

OK, I agree. Bug.

@ranma42
Copy link
Contributor

ranma42 commented Nov 12, 2015

I am not sure if it belongs to the same bug report, but I would also expect

println!("{}", if false { ((1u8 - 5u8) == 42) } else { false });

to report the same warning as

println!("{}", false && ((1u8 - 5u8) == 42));

Instead, the compiler seem to completely disregard the overflow in the first branch of if false, possibly because it detects at compile time that it the overflow is unreachable.

I am not sure if it is desirable for the compiler to report about issues found in dead code or if they should just be "hidden" behind a warning about the dead code. I would definitely not expect them to cause error (as in the const+&& case) and I think they should also not be silently ignored (as in the if false case).

@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 12, 2015

@ranma42 yes, the behavior will now be the same. The warning will be gone since the second expression is unreachable.

The issue with "dead code" here is configurability. Maybe the first boolean expression is a value that is somewhat dynamic:

const N: usize = 0;
const ARR: [i32; N] = [42; N];
const X: bool = (N > 0) && ARR[0] == 99;

This code should not report a warning or an error about ARR[0] being unreachable or erroneous.

@ranma42
Copy link
Contributor

ranma42 commented Nov 12, 2015

@oli-obk I agree that in const-evaluated code it might be undesirable to have these warnings, but at least in "normal" code (including my first example with if) I would rather have a warning (at least about the dead code).

In my opinion, the different warning behaviour between const-evaluated expressions and expressions that are meant for runtime evaluation but that are optimised away could be reasonable. If I expect a boolean expression to be const-evaluated, I am assuming that some of it might be dead code (because of the shortcut operators).

Instead, for normal expressions, my basic assumption is that the compiler is unable to evaluate them before runtime; if they can be evaluated at compile time (at least partially, i.e. if they have dead code), I probably wrote something wrong. If I intentionally write a normal expression with dead code, I would not be surprised if the compiler required me some additional annotation to suppress the warning (cfr. the unused variable warning suppressed by the underscore prefix).

@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 12, 2015

I see your point. That is indeed a different issue and should have it's own issue number. This issue is solely about constant evaluation of the && and || operators

@ranma42
Copy link
Contributor

ranma42 commented Nov 12, 2015

Right, added as #29803.

shahn added a commit to shahn/rust that referenced this issue Nov 17, 2015
As described in rust-lang#29608, the rhs of a logical expression is evaluated
even if evaluation of the lhs means no such evaluation should take
place.
@oli-obk
Copy link
Contributor Author

oli-obk commented Nov 18, 2015

This issue will be postponed until the two const evaluators have been unified

@steveklabnik steveklabnik added T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed A-lang labels Mar 24, 2017
@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jul 24, 2017
@varkor
Copy link
Member

varkor commented Jan 31, 2018

@oli-obk: will this be fixed by #46882?

@oli-obk
Copy link
Contributor Author

oli-obk commented Jan 31, 2018

Oh good point. I'm assuming this'll be solved partially.

false && ((1u8 - 5u8) == 42 will not error, instead produce a warning

@oli-obk
Copy link
Contributor Author

oli-obk commented Jan 31, 2018

I'll add some tests

@oli-obk
Copy link
Contributor Author

oli-obk commented Jan 31, 2018

Nevermind, this is not fixed. After #46882 is merged, it should be as simple as removing all constness checks from

https://github.com/rust-lang/rust/blob/master/src/librustc_mir/hair/cx/expr.rs#L292

@gnzlbg
Copy link
Contributor

gnzlbg commented Dec 6, 2018

What's blocking this?

@oli-obk
Copy link
Contributor Author

oli-obk commented Dec 7, 2018

#49146 is the tracking issue for if and match. Implementing that will automatically resolve && and ||

@Centril Centril added the A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) label Dec 31, 2018
@oli-obk
Copy link
Contributor Author

oli-obk commented Aug 3, 2020

This has been solved together with #49146

@oli-obk oli-obk closed this as completed Aug 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

10 participants