-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
remove Panic variant from InterpError #68969
Conversation
src/librustc/mir/interpret/error.rs
Outdated
@@ -242,6 +251,9 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> { | |||
} | |||
} | |||
|
|||
/// Information about a panic. | |||
/// | |||
/// FIXME: this is not actually an InterpError, and should probably be moved to another module. |
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.
@oli-obk any proposals where to put this? The Debug
impl of this is still used by const-eval and const-prop.
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.
In that case you can move it to src/librustc_mir/interpret
. Maybe create an error handling submodule that for now just contains this type.
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.
Ah I should have been clearer, the type itself is also used in MIR.^^ So the default place would be rustc/mir/mod.rs
I think. But should the Debug
impl also be there?
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.
oh... well, if it's part of the MIR, you need to keep the Debug
impl around for debug printing, as most MIR datastructures can be debug printed.
rustc/mir/mod.rs
seems fine to me
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.
@oli-obk All right, I moved it. But I also realized the name is kind of bad... this is not about panics in general, it is about assertions in particular. It's just that AssertMessage
is already a type alias for the specific PanicInfo<Operand>
that actually gets embedded into MIR.
So what would be a better name? Maybe AssertInfo
? Though the distinction between AssertInfo
and AssertMessage
is entirely not obvious.
fn report_panic_as_lint(&self, source_info: SourceInfo, panic: PanicInfo<u64>) -> Option<()> { | ||
// Somewhat convoluted way to re-use the CTFE error reporting code. | ||
let lint_root = self.lint_root(source_info)?; | ||
let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); | ||
let mut diagnostic = error_to_const_error(&self.ecx, error.into()); | ||
diagnostic.span = source_info.span; // fix the span | ||
diagnostic.report_as_lint( | ||
self.tcx.at(source_info.span), | ||
"this expression will panic at runtime", | ||
lint_root, | ||
None, | ||
); | ||
None | ||
} |
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.
So this is quite a mess. I basically took the error reporting code from use_ecx
, and glued it directly together with the code that actually raises the error -- but at that point there is not really any reason left to even create an InterpError
, except that I don't know what to do instead.
And "this expression will panic at runtime" is factually wrong; run-time panics are caused by Assert
terminators which do not go through this code-path. But that confusion is pre-existing.
Probably, this should not use ConstEvalErr
at all, but I have no idea which part of ConstEvalErr::struct_generic
is geared specifically towards const-prop and should be put here (and removed in its original source).
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.
Probably the best thing would be to take the error reporting code from visit_terminator
, put it into a helper function, and use that. That would also make things more consistent in terms of errors being reported on MIR with and without overflow checks.
I am holding off on this though because I fear that might create some dead code in ConstEvalErr::struct_generic
-- was some code there added just to handle const-prop? If yes, that should be removed then.
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.
And "this expression will panic at runtime" is factually wrong; run-time panics are caused by Assert terminators which do not go through this code-path. But that confusion is pre-existing.
right, it used to be true at the start. Maybe we could just go with a generic "this expression contains erroneous code"?
Probably, this should not use ConstEvalErr at all, but I have no idea which part of ConstEvalErr::struct_generic is geared specifically towards const-prop and should be put here (and removed in its original source).
You can just report a lint directly via self.tcx.sess.span_lint
. After that you should be able to make MachineError
a bug!
in report_as_lint
again.
All this should probably be in separate PRs though, at least the lint and the message change are likely to be noisy.
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 am holding off on this though because I fear that might create some dead code in ConstEvalErr::struct_generic -- was some code there added just to handle const-prop? If yes, that should be removed then.
There shouldn't be, we ignore everything but panic-likes in const prop
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.
There shouldn't be, we ignore everything but panic-likes in const prop
I was referring to this mess:
rust/src/librustc/mir/interpret/error.rs
Lines 146 to 167 in 4d1241f
let mut err = if let (Some(lint_root), false) = (lint_root, must_error) { | |
let hir_id = self | |
.stacktrace | |
.iter() | |
.rev() | |
.filter_map(|frame| frame.lint_root) | |
.next() | |
.unwrap_or(lint_root); | |
tcx.struct_span_lint_hir( | |
rustc_session::lint::builtin::CONST_ERR, | |
hir_id, | |
tcx.span, | |
message, | |
) | |
} else if must_error { | |
struct_error(tcx, &self.error.to_string()) | |
} else { | |
struct_error(tcx, message) | |
}; | |
if !must_error { | |
err.span_label(self.span, self.error.to_string()); | |
} |
Is some of this const-prop hackery, or is this all still needed even if const-prop uses another code path?
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 was more thinking of leaving CTFE with const_err and making const-prop emit some other error... that error is not necessarily about "consts" anyway.
the relevant rfc rust-lang/rfcs#1229 mentions "erroneous code", though that's very vague.
(I am also not sure if the const-prop errors really should be deny-by-default but that is a separate concern.)
They are only deny-by-default because they share the same lint name, after splitting it making it warn-by-default seems ok. Also promoteds should share that lint.
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.
Also promoteds should share that lint.
Aaaahhh, but then it'll become messy again because this means the ConstEvalError
thing will also emit that lint.^^
Also, I think even ignoring that concern I only agree for promoteds that were promoted from a function, not those promoted from a const
.
So, what about this mess, can anyone add comments to explain it and maybe remove what is not needed any more when const-prop switches away?
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.
Also, I think even ignoring that concern I only agree for promoteds that were promoted from a function, not those promoted from a const.
yes that makes sense
So, what about this mess, can anyone add comments to explain it and maybe remove what is not needed any more when const-prop switches away?
We can't change anything here as far as I can tell. This is all needed for CTFE. const prop just made use of the "lint only" case since it only ever fed panic errors into this function.
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.
Whatever "lint only case" means...
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 added a commit that (a) cleans up the control flow a bit and (b) adds some FIXMEs fur stuff that is weird and has no comment explaining it.
// then we'll already catch overflow when we evaluate the `Assert` statement | ||
// in MIR. However, if overflow checking is disabled, then there won't be any | ||
// `Assert` statement and so we have to do additional checking here. | ||
if !overflow_check { |
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 also just realized this entire !overflow_check
makes no sense...
It gets initialized via
let overflow_check = self.tcx.sess.overflow_checks();
but whether this MIR has overflow checks is not a global property! In release builds, function bodies have no overflow checks but const
bodies still have overflow checks.
Ah, but maybe const-prop does not run on const
bodies? At least with associated const though, one could conceivably still want to optimize the MIR even though it cannot be executed... if we don't that will at the very least mean that exceeding_bitshifts
does not happen there. (EDIT: nope, this really does lead to duplicates: #69020 (comment))
And the other part that makes no sense is causing #69020: even with !overflow_check
, division and remainder still get overflow checks.
And of course, for addition, subtraction and multiplication in MIR with overflow checks, check_binary_op
will anyway not be called because those will use CheckedBinOp
, not BinOp
! So, the check is mostly dead code anyway.
We could keep piling up more and more special cases, but this is getting ridiculous. I feel this requires a fundamentally different approach.
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.
So... my gut feeling is that we should stop emitting errors at the Assert
terminators (which only sometimes exist), and always use the arithmetic operation itself as the source of the error (as that will always exist in one form or another, for debug or release builds). Does that sound sensible? (Yes that is a separate PR.)
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.
hmm... That will also solve the situation where we have code paths only run by const prop, because const eval will now also take them. So essentially assert terminators become gotos for miri? Can this work for length checks and such, too?
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 have no idea what you mean... I was talking only about const-prop not emitting errors at Assert
terminators, not Miri in general. Miri in general should implement the Rust Abstract Machine, and there arithmetic is wrapping.
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.
Ok then: const-prop skips assert terminators and treats them like Goto
?
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.
Ok then: const-prop skips assert terminators and treats them like
Goto
?
But doesn't that make "this may panic at runtime" messaging a complete lie?
Only Assert
terminators are the ultimate source of truth for that.
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 guess there are two categories of Assert
terminators:
- always emitted (indexing, division by 0, etc.)
- overflow checks, only in debug mode or with a flag enabled etc.
I don't care too much about what happens with the latter, but I think the former should still be relied upon.
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.
But doesn't that make "this may panic at runtime" messaging a complete lie?
Only Assert terminators are the ultimate source of truth for that.
Fun story: currently, we do not write "this will panic at runtime" when we get our info from Assert
terminators. We only write that when we do not get it from assert terminators.
I don't care too much about what happens with the latter, but I think the former should still be relied upon.
I can see that. However, then we need some other way to fix #61821. Though now that I am thinking about this... considering that const-prop currently stays silent when evaluating a div-by-0 (relying on the panic instead), it probably makes most sense to also make const-prop stay silent when evaluating an out-of-bounds access (relying on the panic instead).
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.
Fun story: currently, we do not write "this will panic at runtime" when we get our info from Assert terminators. We only write that when we do not get it from assert terminators.
That's... the wrongest it can be, wow!
considering that const-prop currently stays silent when evaluating a div-by-0 (relying on the panic instead), it probably makes most sense to also make const-prop stay silent when evaluating an out-of-bounds access (relying on the panic instead).
Yes, all "Assert
guards UB" situations should be treated the same.
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.
On a second thought, this makes no sense... we already don't show out-of-bounds indexing in const-prop. The error there is duplicated because the MIR got duplicated into the promoted. The fix will have to be something promoted-specific.
@bors r+ |
📌 Commit 4e0cecea5090d9ba0df4a8963247df5282d1aa1a has been approved by |
@bors r- I'd like to resolve #68969 (comment) before landing. |
☔ The latest upstream changes (presumably #68725) made this pull request unmergeable. Please resolve the merge conflicts. |
@oli-obk I updated the comments with what you said, and rebased. Please check. |
☔ The latest upstream changes (presumably #69105) made this pull request unmergeable. Please resolve the merge conflicts. |
r=me after another rebase |
- comment for special handling of Shl/Shr - reference a PR
@bors r=oli-obk |
📌 Commit ed2f22c has been approved by |
@bors r=oli-obk |
📌 Commit 33ba83c has been approved by |
remove Panic variant from InterpError The interpreter engine itself does not raise `Panic` errors any more, so remove them from the error enum. Instead, const-prop and const-eval have to do their own handling of panics. I used the opportunity to refactor the const-eval error handling a bit to use the `MachineStop` variant. Also, in const-prop I could do some cleanup as now, no more lints are being reported in `use_ecx`. However, I am quite puzzled by why exactly the linting there works the way it does -- the code can certainly be cleaned up more, but I don't know enough of the intent to do that. I left some questions for the most confusing parts, but for now behavior should be unchanged by this PR (so, all that weirdness I am asking about is pre-existing and merely maintained here). Cc @wesleywiser Fixes #66902 r? @oli-obk
☀️ Test successful - checks-azure |
📣 Toolstate changed by #68969! Tested on commit d538b80. 💔 miri on windows: test-fail → build-fail (cc @oli-obk @eddyb @RalfJung, @rust-lang/infra). |
Tested on commit rust-lang/rust@d538b80. Direct link to PR: <rust-lang/rust#68969> 💔 miri on windows: test-fail → build-fail (cc @oli-obk @eddyb @RalfJung, @rust-lang/infra). 💔 miri on linux: test-fail → build-fail (cc @oli-obk @eddyb @RalfJung, @rust-lang/infra). 🎉 rustc-guide on linux: test-fail → test-pass (cc @JohnTitor @amanjeev @spastorino @mark-i-m, @rust-lang/infra).
miri: fix exact_div Turns out `exact_div` was relying on the broken behavior of `Rem` for `int_min % -1` that was fixed in rust-lang#69002. This PR fixes `exact_div`. Inside rustc, `exact_div` is only used in a single place where the divisor is always positive (in `ptr_offset_from`), so we cannot test the fix in rustc. The Miri test suite covers this through the `exact_div` intrinsic, though (and it is how I found out). One step to rust-lang#69117 (then we also need to address build failures introduced by rust-lang#68969) r? @oli-obk
The interpreter engine itself does not raise
Panic
errors any more, so remove them from the error enum. Instead, const-prop and const-eval have to do their own handling of panics.I used the opportunity to refactor the const-eval error handling a bit to use the
MachineStop
variant.Also, in const-prop I could do some cleanup as now, no more lints are being reported in
use_ecx
. However, I am quite puzzled by why exactly the linting there works the way it does -- the code can certainly be cleaned up more, but I don't know enough of the intent to do that. I left some questions for the most confusing parts, but for now behavior should be unchanged by this PR (so, all that weirdness I am asking about is pre-existing and merely maintained here). Cc @wesleywiserFixes #66902
r? @oli-obk