You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Static checks for &mut in final value of constant with #![feature(const_mut_refs)] #71212
On stable, we prevent users from creating an &mut that points to memory inside a const 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 a constlike so:
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.
static mut is also an interesting case. Should the following compile? Perhaps, although with my proposal the user would be forced to wrap the initializer of FOO_MUT in a const fn. This suggests to me that checking for &mut in the type of a const is not the correct solution.
Another interesting question here could be aliasing. Usually mutable references are unique. Does that mean that the following is UB because uniqueness got violated (FOO was accessed through a different place between creation and use of FOO_MUT)?
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. NULL and A currently compile on stable and, assuming that I'm right that neither A nor B dangle, reading from either one is not UB. B, however, must fail to compile, but a type-based check on the final value of a constant would reject NULL as well.
// Compile on stable and work as expected.constNULL:*muti32 = ptr::null_mut();constA:*consti32 = &4;// Must not compile.constB:*muti32 = &mut4;fnmain(){println!("{}",unsafe{*A});// unsafe { *B = 4 } // Bad news}
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...
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 GlobalAlloc::Static, we can do this.
#![feature(const_mut_refs)]pubmod a {#[no_mangle]pubstaticmutFOO:&mut[i32] = &mut[42];}pubmod b {#[no_mangle]pubstaticmutBAR:&mut[i32] = unsafe{&mut*crate::a::FOO};}fnmain(){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. &mut *crate::a::FOO should return the original pointer.
Activity
ecstatic-morse commentedon Apr 16, 2020
static mutis also an interesting case. Should the following compile? Perhaps, although with my proposal the user would be forced to wrap the initializer ofFOO_MUTin aconst fn. This suggests to me that checking for&mutin the type of aconstis not the correct solution.7 remaining items
RalfJung commentedon Apr 17, 2020
Another interesting question here could be aliasing. Usually mutable references are unique. Does that mean that the following is UB because uniqueness got violated (
FOOwas accessed through a different place between creation and use ofFOO_MUT)?RalfJung commentedon Apr 17, 2020
(Also strangely I did not get emailed about the ping above.)
ecstatic-morse commentedon Apr 17, 2020
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.
NULLandAcurrently compile on stable and, assuming that I'm right that neitherAnorBdangle, reading from either one is not UB.B, however, must fail to compile, but a type-based check on the final value of a constant would rejectNULLas well.JohnTitor commentedon May 17, 2020
Triage: the ICE no longer occurs with the latest nightly by #71665.
RalfJung commentedon May 17, 2020
The bug is not primarily about the ICE though, it is about what static checks we need in place to avoid mis-behaved
&mutconstants.RalfJung commentedon May 17, 2020
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...
oli-obk commentedon May 19, 2020
If we make validation and interning stop when encountering
GlobalAlloc::Static, we can do this.RalfJung commentedon May 20, 2020
@oli-obk That would be awesome! I laid down my thoughts in #72396. If that works, I'd be really happy. :D
Rollup merge of rust-lang#72934 - christianpoveda:mut-borrows-in-cons…
oli-obk commentedon Dec 4, 2020
Another fun bug with
static mutandconst_mut_refs:https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=baf2a1bbbf7ba1b5a1c9d7015c2d5b2c
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.
RalfJung commentedon Dec 5, 2020
@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.
&mut *crate::a::FOOshould return the original pointer.oli-obk commentedon Dec 7, 2020
It's indeed a separate bug, but also a blocker for this feature gate