Comments (17)
The reborrow used to create y
makes x
unsuable for 'static
(forever). The state of x
after the move is akin to how replace_with
functions. Or std::mem::replace
(for the duration of the method body), for that matter.
There's more discussion in this RFC thread.
I personally don't feel there are strong enough upsides for language support, e.g. DerefMove
for &'static mut T
. But either (the originally posted) fn take
is sound or replace_with
is unsound.
fn take<T: Send>(reference: &'static mut T) -> T {
let (sender, receiver) = std::sync::mpsc::channel();
std::thread::spawn(move || {
replace_with::replace_with_or_abort(reference, |t| {
let _ = sender.send(t);
loop {}
})
});
receiver.recv().unwrap()
}
replace_with
isn't available on the playground or I'd link a runnable example. But an example usage is
let foo: &'static mut NotDefaultNotCopy = Box::leak(Box::new(NotDefaultNotCopy([1; 20])));
let reborrowed_even = &mut *foo;
let foo_taken = take(reborrowed_even);
println!("{:?}", foo_taken.0);
// Trying to use `foo` is an error because `*foo` is exclusively reborrowed forever
from rust.
I agree that this is sound:
fn take<T>(reference: &'static mut T) -> T {
unsafe { core::ptr::read(reference) }
}
It would be fairly easy to prove this in Rustbelt as well.
Not sure if it's worth having special support for this in the borrow checker, a dedicated method seems more clear / less magic to me.
from rust.
Miri also doesn't complain about this program, one which is surely not what you intend: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=4a15c73887bce9565554ebf5b12e3627
from rust.
Original(?) discussion started here.
from rust.
@Ddystopia your take
does not move out, it does a typed copy. The demonstration you want to write cannot be written in surface Rust because you can't get past the compiler frontend. That's the whole point of this issue.
To write the demo you want, you must use custom MIR: https://doc.rust-lang.org/nightly/std/intrinsics/mir/index.html
from rust.
In any case, I think the basic reasoning here is wrong: The 'static
bound doesn't help because you can reborrow a &'static mut
into another &'static mut
.
If the following entirely safe code were to be allowed to compile, we would have access to a moved-from value:
#[derive(Debug)]
struct NotCopy(u8);
fn main() {
let x: &'static mut NotCopy = Box::leak(Box::new(NotCopy(0u8)));
let y: &'static mut NotCopy = &mut *x;
let z = *y;
println!("{:?}", *x); // oops, use of moved-from value
}
from rust.
Thanks for the correction!
from rust.
I do agree that there might not be urging need for this, but it sometimes might be useful during embedded development and if something will change with borrow checker's attitude to moving out of mutable references, then it might not take a lot of extra work to consider adding this feature, which will not break anything and apparently sound.
from rust.
which will not break anything and apparently sound.
There was a potentially breaking use case in the RFC thread, depending on how the decision goes. As far as I know there hasn't been an FCP on the topic. That said, opinions did seem favorable on the side of this being sound.
That RFC was closed in part due to concerns about adding an API that aborts. I will note that a proposal to add a function like take
in the OP (which is limited to the &'static mut _
case) also gives an opportunity to bless the operation as sound without introducing an aborting API (and without trying to tackle unwinding as a whole).
Blessing this operation means that every &'static mut T
can bet converted into a newtype which is analogous to a &'static mut Option<T>
(which you can move T
into and, conditionally, out of; conditionally borrow; etc).
from rust.
How would this interact with static mut
items? Yes taking a &mut is unsafe, but not because you could move out of it. Would it simply be disallowed? I feel like accidentally or intentionally making a static item inaccessible by way of borrow checker would be really weird.
from rust.
Yes taking a &mut is unsafe, but not because you could move out of it.
@LunarLambda I would argue that it's equivalent. If you gave a &'static mut
from a static to a function, you are making the static inaccessible. Whatever it is inaccessible due to moving out or due to having a unique reference pointing to the static does not really matter.
Besides, note that references to static mut
s are being deprecated.
from rust.
If you pass a reference to a function the item becomes inaccessible for the duration of the function, not permanently.
Also, you can still create references to static mut
via addr_of_mut and reborrowing, which is allowed so long as you observe the proper invariants. Just like with any other raw pointer. Only the &mut
syntax directly on the static item is being disallowed.
from rust.
If you pass a reference to a function the item becomes inaccessible for the duration of the function, not permanently.
Not if you pass a 'static
reference (example).
from rust.
there's nothing being borrowed in that example. you're passing the return value of Box::leak. It "consumes" the reference because you're not binding it to anything.
from rust.
@LunarLambda a &'static
reference can be used the same, no matter how you obtained it. here is an example which uses a static mut
and binds the reference to a variable, nothing changes.
from rust.
I see, nevermind then. Apologies.
from rust.
Miri also doesn't complain about this program, one which is surely not what you intend: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=4a15c73887bce9565554ebf5b12e3627
Thank you for note! Here is another example, which is closer to what I wanted to demonstrate playground
I also tried custom MIR, but compiler kept ICE-ing and I gave up
from rust.
Related Issues (20)
- rustdoc: panic when using `macro@` and `!` for referencing a macro in documentation HOT 2
- If-else type checking fails with trait method calls and closures HOT 5
- Lots of testsuite failures on powerpc-unknown-linux-gnu after #118709 HOT 4
- Taking reference to function gets optimized to be 0x1 HOT 5
- document args for `-Zbuild-std` when folks aren't building everything HOT 5
- Well-formedness analysis pass on trait impl paniced HOT 3
- Unnecessary move in trait object comparison HOT 1
- Type inference complains about unknown size for `dyn Any` HOT 3
- ICE(non_lifetime_binders): const bound params not handled correctly HOT 3
- diagnostics should prefer naming items through the extern prelude instead of doc-hidden type aliases
- async lambda with capture ICE HOT 4
- std::net::TcpStream::connect_timeout on vxworks HOT 4
- async lambda fails to copy a value that is Copy HOT 12
- nightly ICE when building flexstr in release mode HOT 8
- `hir::Body`'s documentation incorrectly suggests it doesn't contain parmaeter info for closures
- error: internal compiler error: compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs:486:17: cannot relate region: LUB('{erased}, '{erased}) HOT 12
- Help needed finding a test that changes behaviour when changing DefiningOpaqueTypes::No to Yes HOT 3
- Binary size creep on Fuchsia after commit 5ced3da HOT 6
- Type mismatch is incorrectly attributed in certain closures / async blocks
- ICE: Found unstable fingerprints for evaluate_obligation - computing whether enum is freeze - optimizing MIR
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust.