-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Raw pointer deref of uninhabited type allowed in const fn #77694
Comments
@rustbot modify labels to +A-raw-pointers +A-const-fn |
cc @rust-lang/wg-const-eval |
Ah, that looks like the const version of the old "uninhabited match" problem... The MIR for
So somehow the deref already vanished, and hence the const analysis cannot catch it. But doesn't unsafety checking also happen on the MIR? Why does that work? |
It seems that whenever the dereference is not bound to a variable, it compiles, but whenever bound to a variable, it fails to compile: const unsafe fn const_deref() {
use core::convert::Infallible;
const INFALLIBLE: *const Infallible = [].as_ptr();
match *INFALLIBLE {
n => {}, // <--- rightfully claims I need #![feature(const_raw_ptr_deref)]
//_ => {}, // <--- compiles fine
};
} |
I don't believe this is an unsoundness. Unsafe code is required to cause anything here.
That's the final MIR, since without |
Agreed. This is a case of "oops a nightly-only feature is available on stable", which is bad, but it is not an unsoundness. |
Assigning |
The initial MIR looks like this: fn unreachable() -> ! {
let mut _0: !; // return place in scope 0 at test2.rs:1:34: 1:35
let mut _1: !; // in scope 0 at test2.rs:1:36: 6:2
let mut _2: !; // in scope 0 at test2.rs:5:5: 5:25
let mut _3: *const std::convert::Infallible; // in scope 0 at test2.rs:5:12: 5:22
bb0: {
StorageLive(_1); // scope 0 at test2.rs:1:36: 6:2
StorageLive(_2); // scope 0 at test2.rs:5:5: 5:25
StorageLive(_3); // scope 0 at test2.rs:5:12: 5:22
_3 = const INFALLIBLE; // scope 0 at test2.rs:5:12: 5:22
// ty::Const
// + ty: *const std::convert::Infallible
// + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ test2[317d]::unreachable::INFALLIBLE), const_param_did: None }, [], None)
// mir::Constant
// + span: test2.rs:5:12: 5:22
// + literal: Const { ty: *const std::convert::Infallible, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ test2[317d]::unreachable::INFALLIBLE), const_param_did: None }, [], None) }
FakeRead(ForMatchedPlace, (*_3)); // scope 0 at test2.rs:5:11: 5:22
unreachable; // scope 0 at test2.rs:5:11: 5:22
}
bb1: {
unreachable; // scope 0 at test2.rs:5:5: 5:25
}
bb2: {
StorageDead(_2); // scope 0 at test2.rs:5:24: 5:25
unreachable; // scope 0 at test2.rs:1:36: 6:2
}
bb3: {
StorageDead(_3); // scope 0 at test2.rs:6:1: 6:2
StorageDead(_1); // scope 0 at test2.rs:6:1: 6:2
return; // scope 0 at test2.rs:6:2: 6:2
}
} So probably the issue is that const-checking ignores |
oh... yea.. we ignored it on purpose... "because it doesn't actually do anything" 🙃 I guess we should visit all places within statements that we otherwise ignore during const-checking? |
Well, at least we need to visit |
Do we really? The |
Oh wait, we don't call |
Proposed a fix: #80199 |
also const-check FakeRead We need to const-check all statements, including `FakeRead`, to avoid issues like rust-lang#77694. Fixes rust-lang#77694. r? `@oli-obk`
The code below compiles as of 1.46, but I'm not sure it should, since it dereferences a raw pointer in a const block, which is only allowed in nightly with the
#![feature(const_raw_ptr_deref)]
flag:The text was updated successfully, but these errors were encountered: