-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
suppress errors in const eval during selection #81339
Conversation
Some changes occured to rustc_codegen_cranelift cc @bjorn3 |
| | ||
LL | fn test<const N: usize>() -> [u8; N - 1] { | ||
| ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow | ||
| ----- required by this bound in `test` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an error quality regression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. We previously didn't even mention that the errors was caused by the test::<0>()
call which is definitely an improvement.
We probably want to reevaluate the constant when emitting the selection error to actually emit why the evaluation failed. so that we get both error messages.
@bors try @rust-timer queue |
Awaiting bors try build completion. |
@bors try- edit: nm, we already use the |
⌛ Testing commit 33ee18a with merge 182a10535327b82daa53b34fcb510489ec7b7632... |
💔 Test failed - checks-actions |
The job Click to see the possible cause of the failure (guessed by this bot)
|
@bors try @rust-timer queue |
Awaiting bors try build completion. |
⌛ Trying commit 33ee18a with merge 16305df2fb3846267c4f2537ae4d0f678e170259... |
☀️ Try build successful - checks-actions |
Queued 16305df2fb3846267c4f2537ae4d0f678e170259 with parent a8f7075, future comparison URL. @rustbot label: +S-waiting-on-perf |
Finished benchmarking try commit (16305df2fb3846267c4f2537ae4d0f678e170259): comparison url. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up. @bors rollup=never |
Regressions of up to 2.4% on ctfe-stress incr-full and up to 1.7% otherwise. For full the max regression is 0.3%, for incr-full excluding ctfe-stress 1.0%, for incr-unchanged up to 1.2% and up to 1.7% for incr-patched. |
let mut key = key; | ||
key.param_env = key.param_env.with_reveal_selection(); | ||
match tcx.eval_to_const_value_raw(key) { | ||
// try again with reveal all as requested |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will try again with reveal "user facing" though, won't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, didn't update all the comments yet. Opened this case I wanted other people to look at this PR in case there's a fundamental issue I've missed.
let mut key = key; | ||
key.param_env = key.param_env.with_user_facing(); | ||
match tcx.eval_to_allocation_raw(key) { | ||
// try again with reveal all as requested |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You lost this comment.
Also, the Reveal
logic here is an exact duplicate of the one above, isn't it? By now it looks non-trivial enough to justify doing some refactoring to share it.
match error.kind { | ||
err_inval!(Layout(LayoutError::Unknown(_))) | ||
| err_inval!(TooGeneric) | ||
| err_inval!(AlreadyReported(_)) => {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are those exact three treated differently here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will cause some new issues though -- it will be much harder to avoid printing the same const error multiple times.
when const eval prints an error the InterpError
is AlreadyReported
. So we don't return Silent
here to prevent emitting the error twice.
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric)
because these result in ErrorHandled::TooGeneric
which we still want to emit
Probably needs a comment as well ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are quoting me entirely out of context here.^^ In that quote I was referring to "have the query return a Result".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when const eval prints an error the InterpError is AlreadyReported. So we don't return Silent here to prevent emitting the error twice.
Well but it means we hit the code path below for reporting it? Or is report_as_lint
et al silent for AlreadyReported
?
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) because these result in ErrorHandled::TooGeneric which we still want to emit
Oh we do? I thought TooGeneric should never be emitted, it means "please re-evaluate with RevealAll
?
Yeah, that would definitely be the much more sensible approach: have the query return a The question is if we can find a nice error type to put into that |
That (have the query return a Result) will cause some new issues though -- it will be much harder to avoid printing the same const error multiple times. |
I think that's fine as we only have to evaluate twice when failing the compilation (ignoring that we sometimes only lint instead of emitting an error rn) which tbh seems fine and it does avoid having to deal with "Using literally |
Exactly 50% more executions of All in all, the perf regression is absolutely benign, mostly below 1% and only for the CTFE stress test we reach 2.4%. But I think there are multiple ways we can think about improving the situation. One thing we need to look into is the metadata encoding of the queries. Since most of the time the content is the same, we need to check whether we only encode the content once. The other thing is figuring out more ways to ensure we don't re-run a build if not absolutely necessary. Multiple questions here:
|
Yeah, that's fair... though having 1 query turn into 3 nested queries is still pretty heavy. Queries are rather expensive. And doesn't also triple the cache? |
think so yeah, we have to try evaluating consts from other crates with
Not exactly sure what you mean here. I guess this is about returning an optional
I am not sure if having separate queries would be useful. We still need to pass in the param env so that we can normalize projections during const eval. And even if we were to not add
That would be good i think, don't know how easy this is to implement. Opened a zulip topic for this: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/deduplicate.20query.20cache |
yes, exactly that.
Many times we'll be using different generics to do that, so we'd be recomputing anyway. Of course if that constant is very expensive to compute, then that's a different story... Oh god, we could make the decision for whether to cache the result depend on the evaluation's instruction counter |
const_evaluatable_checked: Stop eagerly erroring in `is_const_evaluatable` Fixes rust-lang#82279 We don't want to be emitting errors inside of is_const_evaluatable because we may call this during selection where it should be able to fail silently There were two errors being emitted in `is_const_evaluatable`. The one causing the compile error in rust-lang#82279 was inside the match arm for `FailureKind::MentionsParam` but I moved the other error being emitted too since it made things cleaner imo The `NotConstEvaluatable` enum \*should\* have a fourth variant for when we fail to evaluate a concrete const, e.g. `0 - 1` but that cant happen until rust-lang#81339 cc `@oli-obk` `@lcnr` r? `@nikomatsakis`
don't have the capacity to work on this rn |
needs MCP but was surprisingly simple to implement.
Do not emit errors during const eval when checking constants inside of the trait system.
We do this by adding a
Reveal::Selection
which behaves similar toReveal::UserFacing
butsupresses errors during const eval.
This allows coherence to work properly with
feature(const_evaluatable_checked)
andimproves the error location from abysmal to somewhat acceptable.
r? @oli-obk