-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Static checks for &mut
in final value of constant with #![feature(const_mut_refs)]
#71212
Comments
static mut FOO: i32 = 4;
const FOO_MUT: &mut i32 = unsafe { &mut FOO };
fn main() {
*FOO_MUT = 2;
} |
Label race XD |
cc @rust-lang/wg-const-eval |
static mut FOO: i32 = 4;
const FOO_MUT: &mut i32 = unsafe { &mut FOO };
fn main() {
*FOO_MUT = 2;
} Another interesting question here could be aliasing. Usually mutable references are unique. Does that mean that the following is UB because uniqueness got violated ( static mut FOO: i32 = 4;
const FOO_MUT: &mut i32 = unsafe { &mut FOO };
fn main() { unsafe {
FOO += 5;
*FOO_MUT = 2;
} } |
(Also strangely I did not get emailed about the ping above.) |
Ah, that's a good point. In that case, I think we can ignore that example as an argument against the type visitor approach. Perhaps this is a better example. I believe that things at the top level of a const initializer have a static storage duration. I'm not actually sure whether this is user-observable and guaranteed since rvalue static promotion is pretty aggressive inside constants. // Compile on stable and work as expected.
const NULL: *mut i32 = ptr::null_mut();
const A: *const i32 = &4;
// Must not compile.
const B: *mut i32 = &mut 4;
fn main() {
println!("{}", unsafe { *A });
// unsafe { *B = 4 } // Bad news
} |
Triage: the ICE no longer occurs with the latest nightly by #71665. |
The bug is not primarily about the ICE though, it is about what static checks we need in place to avoid mis-behaved |
What actually happens currently is that interning detects the mutable reference in a const and complains about it -- good. I wonder if validation should do that check, instead... but currently validation is a separate query so there is always the risk that it does not run. :/ Things would be so much easier if the raw const query would always do validation and thus ensure that only validated values ever enter the rest of the compiler... |
If we make validation and interning stop when encountering |
…ts, r=oli-obk forbid mutable references in all constant contexts except for const-fns PR to address rust-lang#71212 cc: @ecstatic-morse
Another fun bug with #![feature(const_mut_refs)]
pub mod a {
#[no_mangle]
pub static mut FOO: &mut [i32] = &mut [42];
}
pub mod b {
#[no_mangle]
pub static mut BAR: &mut [i32] = unsafe { &mut *crate::a::FOO };
}
fn main() {
unsafe {
assert_eq!(a::FOO.as_ptr(), b::BAR.as_ptr());
}
} The assertion fails, even though I belive that it should most definitely not. Only base allocations of statics have a guaranteed address and won't get deduplicated. |
@oli-obk Shouldn't that be a separate bug? That has nothing to do with static checks or so, this seems like a codegen issue. |
It's indeed a separate bug, but also a blocker for this feature gate |
On stable, we prevent users from creating an
&mut
that points to memory inside aconst
by forbidding the creation of mutable references during const-eval. This limitation is only temporary, see #57349. We have a feature flag,const_mut_refs
, that allows users to create mutable references, but no attempt is made to prevent&mut
from escaping into the final value of aconst
like so:This errors on the current nightly, and if there were a feature gate that allowed it, we would get an ICE:
I think we've not yet settled on the semantics we want. We're allowing them in
const fn
and relying on the borrow checker to prevent references from escaping.The text was updated successfully, but these errors were encountered: