-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Do not assert layout in KnownPanicsLint. #144226
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
base: master
Are you sure you want to change the base?
Conversation
r? @davidtwco rustbot has assigned @davidtwco. Use |
Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri This PR changes a file inside Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred to the CTFE machinery |
@@ -243,6 +243,17 @@ impl<'tcx, Prov: Provenance> std::ops::Deref for ImmTy<'tcx, Prov> { | |||
} | |||
|
|||
impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { | |||
#[inline(always)] | |||
pub fn try_from_immediate(imm: Immediate<Prov>, layout: TyAndLayout<'tcx>) -> Option<Self> { |
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'm not a fan of these functions. The point of the assertions is that they are a last line of defense to detect defective callers. They are not exhaustive checks. If the caller can't ensure that the value has the right type, that can only be fixed in the caller.
IOW, matches_abi
here really is more of a maybe_matches_abi
. It is necessary, but not sufficient. And trying to make it sufficient is the wrong approach; the right approach is figuring out why someone is feeding bogus data into these functions.
|
||
use std::fmt::Debug; | ||
|
||
static STATIC_1: dyn Debug + Sync = *(); |
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.
For instance, this is a clearly ill-formed static. Nothing should ever look at its MIR. Trying to make the MIR interpreter APIs resistant against bogus MIR is a pointless game of whack-a-mole.
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.
yea those cases are straight forward to prevent within type_of
, we don't even need to compute the layout, just doing a sizedness 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.
That doesn't quite work since we allow extern statics that have extern types, which are unsized.
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.
Well, we can check the tail manually for slices and dyn trait
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 that requires unfolding the type which will trigger the same cycle error, 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.
These all seem to be standard cases of "ill-formed MIR gets too far into the pipeline". We should never run any MIR passes on ill-formed MIR; it is a waste of effort to try and fix this inside every individual pass.
I agree, but fixing this is general is hard too. We have an A "cleaner" way would be to ensure we never produce a constant with mismatching ABI, be it as a |
These are statics failing the "it must be sized" check. It's not some impossible where bound. I don't see what is so hard about marking them as tainted so nothing else ever touches them again. It's the exact same thing as a static whose initializer body is plainly ill-typed. |
7e54047
to
a825a96
Compare
@RalfJung this latest version prevents creating the erroneous constants altogether. Do you agree with this version? |
This comment has been minimized.
This comment has been minimized.
a825a96
to
a250112
Compare
This comment has been minimized.
This comment has been minimized.
Yeah, that looks much better, thanks. I'm not familiar with MIR building so I can't approve this on my own, however. |
It's not ready yet. Just checking sizedness is not enough, as some non-sized types are OK too, like extern types. And using layout causes cycles. |
Extern types can only work with extern statics, right? And even then, that seems kind of cursed. Did we intentionally allow that or just forget to disallow it? |
Or inside pointers. And pointers to extern types are scalars.
It's intentional. We have a run-make test to verify this works. |
Pointers to extern types are sized so there is no problem with them, those should just work.
|
The failing test is this one: rust/tests/run-make/static-extern-type/use-foo.rs Lines 3 to 7 in a7a1618
As a foreign type Checking whether |
Yeah, that is a very odd test, I didn't think we'd allow extern statics with unknown size. Interestingly, we reject What is not entirely clear to me is why we'd care about whether |
All the issues referenced here seem to be about statics that are unsized-with-metadata. You can check for this without knowing the layout; just call This still has to normalize some things though, so that coroutine case could become interesting. But it's okay for that code to error, it just can't ICE. |
// Still, producing a single scalar constant would be inconsistent, as pointers to | ||
// non-`Sized` types are scalar pairs. Avoid an ICE by producing an error constant. | ||
let guar = | ||
tcx.dcx().span_delayed_bug(span, format!("static's type `{ty}` is not Sized")); |
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.
tcx.dcx().span_delayed_bug(span, format!("static's type `{ty}` is not Sized")); | |
tcx.dcx().span_delayed_bug(span, format!("static's type `{pointee}` is not Sized")); |
Wouldn't an alternative be to change the type of the static itself to Cc @oli-obk |
a250112
to
1a23d74
Compare
// Still, producing a single scalar constant would be inconsistent, as pointers to | ||
// non-`Sized` types are scalar pairs. Avoid an ICE by producing an error constant. | ||
let guar = | ||
tcx.dcx().span_delayed_bug(span, format!("static's type `{ty}` is not scalar")); |
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.
ty
is not the type of the static, it's the type of a pointer to the static.
let const_ = if let Ok(layout) = layout | ||
&& let BackendRepr::Scalar(..) = layout.backend_repr |
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.
As noted before, I think the better approach would be to give the static an Error
type -- otherwise, there might well be other consumers all over rustc that assume things about a static
s type, that all need to get a fix like this.
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 tried that, and for some reason that was not enough to fix the ices. I did try to find why error tainting failed.
tests/ui/coroutine/layout-error.rs
Outdated
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 is it okay for this to cycle-error? Having the type of a static depend on its value does seem quite cursed.^^
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.
Is a static's type meaningfully different from a function's return type? Because it's not about its evaluated value, but just how opaque types work.
I don't think this use case is particularly unusual and expect people will want to be using TAITs like this.
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.
Is a static's type meaningfully different from a function's return type?
Hm... not really, the problem is just that the constraint on the type cannot be so easily expressed as a trait query. For return types it's T: Sized
, but for static types it's... T: Pointee<Metadata = ()>
or so?
that would mean moving these checks to |
1a23d74
to
8095c2d
Compare
This PR modifies |
The latest commit tries that. I think it's worse because it breaks passing tests. |
This comment was marked as outdated.
This comment was marked as outdated.
8095c2d
to
7c64961
Compare
Fixes #121176
Fixes #129109
Fixes #130970
Fixes #131347
Fixes #139872
Fixes #140332