I am trying to write a mem::swap function without using any std lib functions. i am totally new to rust and still trying to make sense of how to use rust language.
below is my code
fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
let mut t: &mut T = y;
y = x;
x = t;
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
let mut t = Box::new(0);
swap(&mut x, &mut y);
}
and i am facing below error
error: lifetime may not live long enough
--> src/main.rs:4:29
|
1 | fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
| - - let's call the lifetime of this reference `'2`
| |
| let's call the lifetime of this reference `'1`
...
4 | let mut t: &mut T = y;
| ^ assignment requires that `'2` must outlive `'1`
|
help: consider introducing a named lifetime parameter
|
1 | fn swap<'a, T: std::fmt::Display>(x: &'a mut T, y: &'a mut T) {
| +++ ++ ++
what does 'lifetime may not live long enough' mean ?
is there a simple way to write mem::swap code in rust ?
You need to Copy the data. The reference you're using is useless for this purpose. You need to actually alter what both x and y reference.
For example:
fn swap<T>(a: &mut T, b: &mut T) where T : Copy {
(*a,*b) = (*b, *a)
}
fn main() {
let mut a = 1;
let mut b = 2;
swap(&mut a,&mut b);
println!("a={}, b={}", a, b);
}
If you set up the conditions here, it's really a one-liner, Rust will figure out the "temporary" stuff for you. In fact, having a function to do this is actually kind of overkill, since you can just do that single line anywhere in your code as you would normally.
Maybe you want to optimize this around boxed values, taking Box<T> as an argument instead, in which case you could swap references within the box instead of copying, but that's a specialization.
How about using core::ptr::swap to swap raw pointers *mut T.
use core::ptr::swap;
fn custom_swap<T>(x: &mut T, y: &mut T) {
unsafe {
(x as *mut T).swap(y as *mut T);
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
println!("x={}, y={}", x, y);
custom_swap(&mut x, &mut y);
println!("x={}, y={}", x, y);
}
output
Hello, world!
x=5, y=42
x=42, y=5
Related
There is a code that produces the following error:
fn foo<'a, F1, F2>(f: F1)
where
F1: FnOnce(&'a mut i32) -> F2,
F2: FnOnce() + 'a,
{
let mut a = 0;
f(&mut a)();
}
fn main() {
foo(|a| {
|| {
*a += 1;
()
}
});
}
error[E0597]: `a` does not live long enough
--> src/main.rs:7:7
|
1 | fn foo<'a, F1, F2>(f: F1)
| -- lifetime `'a` defined here
...
7 | f(&mut a)();
| --^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'a`
8 | }
| - `a` dropped here while still borrowed
I'm very confused because error message says that a is still borrowed but foo returns nothing!
Your code has two issues:
a Lifetime issue
it tries to return a closure
1. The lifetime issue
You can reduce the example in your question to
fn foo<'a, F1>(f: F1)
where
F1: FnOnce(&'a mut i32),
{
let mut a = 0;
f(&mut a);
}
fn main() {
foo(|a| {
*a += 1;
});
}
and here you can probably see more clearly, that
fn foo<'a, F1>(f: F1)
where
F1: FnOnce(&'a mut i32)
means, that the caller of foo can decide, what 'a
will be.
But in
let mut a = 0;
f(&mut a);
you create a, which has its concrete lifetime (essentially
the body of foo) and try to call f with it. But 'a which
the caller has chosen, doesn't need to have to do anything
with the lifetime of a, it can be wildly larger for example.
Worded differently
fn foo<'a, F1>(f: F1)
where
F1: FnOnce(&'a mut i32)
means: If you call foo you can hand it something function
like f (function pointer, closure, ...), which needs its parameter
to live at least as long as 'a. 'a could be 'static
for example.
So inside foo you can't just create a thing with its concrete
lifetime and hand if to f, as you don't know, what 'a the
caller of foo will choose.
You might now be surprised, that
fn foo<F1>(f: F1)
where
F1: FnOnce(&mut i32),
{
let mut a = 0;
f(&mut a);
}
fn main() {
foo(|a| {
*a += 1;
});
}
compiles just fine, but that is simply, because foo in this example desugars to
fn foo<F1>(f: F1)
where
F1: for<'a> FnOnce(&'a mut i32),
{
let mut a = 0;
f(&mut a);
}
which means, that not the caller of foo decides, what the lifetime 'a will be, but f has to be something, that can work with a parameter of any lifetime. So foo can choose 'a in this case.
But to be able to return anything, which has the lifetime 'a chosen by foo, you would need to be able to write it into foos signature, which you can't, to the best of my knowledge.
2. it tries to return a closure
The Rust Book, "Returning Closures" tells us, you can't
return closures.
But
fn returns_closure(a: &mut i32) -> impl FnMut() + '_ {
|| {
*a += 1;
println!("{}", *a);
}
}
fn main() {
let mut sum: i32 = 5;
let mut f = returns_closure(&mut sum);
f();
f();
let mut sum2: i32 = 10;
let mut g = returns_closure(&mut sum2);
g();
g();
}
just works fine for me on rustc version 1.58.1.
The Rust Book, "Returning Types that Implement Traits" tells us that you can use the
impl SomeTrait syntax only in return types of functions and methods, which
always return the same concrete type on all function exits.
So the above syntax doesn't apply to closures.
But with generic types we can still do something similar.
fn foo<F1, F2>(f: &mut F1)
where
F1: FnMut(i32) -> F2,
F2: FnMut(),
{
let mut g = f(1);
g();
g();
let mut h = f(2);
h();
h();
}
fn main() {
foo(&mut (|_a: i32| || println!("wtf")));
foo(&mut (|_a: i32| {
let mut a = 5;
move || {
a += 1;
println!("wtf: {}", a);
}
}));
}
still works fine for me. So it seems as long as the compiler can
figure out the concrete types and the closure returning a closures
also always returns the same concrete type, it works for
rustc 1.58.1.
So my guess is, the syntax simply lacks. There needs to be
some syntax to write something like the following pseudo code:
fn foo<F1, F2>(f: &mut F1)
where
F2: FnMut(),
F1: for<'a> FnMut(&'a mut i32) -> F2 + 'a,
{
...
}
I guess the lifetime bound is part of the type at the moment and so
the caller, which chooses F2 would need to know the required lifetime,
that gets choosen in the call ... but thats just guessing.
As the required lifetime bound shouldn't influence the size
needed for the closure returned by f,
something like that might be possible?
In
fn foo2<F1>(f: &mut F1)
where
F1: for<'a> FnMut(&'a mut i32) -> Box<dyn FnMut() + 'a>,
{
...
}
we can neatly express what we want at the unfortunate cost of allocating ...
But now f can of course return different closures with different types
wrapped up in the Box, so it is also more flexible.
My question here is quite specific. I want to disable implicit deref coercions (let's say because I don't like them). More specifically, I want this code to fail:
fn main() {
let x = Box::new(0);
let mut y = &x;
y = &mut y;
println!("GOT {}",*y);
}
To my mind, this is a pretty nonsensical example. But, it compiles because (I believe) &mut T coerces to T and, hence, the statement y = &mut y is a nop.
Assuming this is right, how do I prevent Rust from doing this? I tried, for example, using #[no_implicit_prelude] but with no joy.
The code you have given does not actually use any auto-dereferencing. The type of y is &Box<i32> and the println works because the Display formatting for Box is to just delegate to its contents Display implementation.
If I change your example slightly, we can bring auto-dereferencing into play:
fn main() {
let x = Box::new(0);
let mut y: &i32 = &x; // <-- Deref impl is used here
y = &mut y;
println!("GOT {}", y);
}
You cannot disable any traits that are implemented for built-in types. You could make your own Box that doesn't implement Deref:
use std::{boxed, fmt};
struct Box<T>(boxed::Box<T>);
impl<T> Box<T> {
pub fn new(value: T) -> Self {
Self(boxed::Box::new(value))
}
}
impl<T: fmt::Display> fmt::Display for Box<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
Auto-dereferencing does not work:
fn main() {
let x = Box::new(0);
let mut y: &i32 = &x; // <-- Error: expected `i32`, found struct `Box`
y = &mut y;
println!("GOT {}", y);
}
But you can still print the box itself:
fn main() {
let x = Box::new(0);
let mut y = &x;
y = &mut y;
println!("GOT {}", y); // y: &Box<i32>
}
I'm not sure why you would do this though. You will have to re-implement a lot of Box functionality to make this generally useful, and it isn't at all clear what are the advantages of not having a Deref impl.
The following code doesn't compile, because x is used after move (since x has type &mut u8, which does not implement the Copy trait)
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y = x;
x;
}
And as I understand y implicitly has type &mut u8
But if I specify the type of y explicitly it compiles. The following code compiles
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y: &mut u8 = x;
x;
}
By the way if I change let y: &mut u8 = x; to let y: &u8 = x; it also compiles.
It seems to me nothing has changed, y is &mut u8 in the first example and it is &mut u8 in the second but the former doesn't compile and the latter does compile.
Why? What's the difference?
&mut u8 is not a complete type. All reference types must have a lifetime parameter on them. When you elide it, the Rust compiler must infer it, and it will pick the shortest lifetime possible. In your first example, the first step of desugaring is (using a fake syntax from the Rustonomicon):
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until it's use at the end
let y = x;
x;
}
}
This is still not completely explicit, since the type of y is still not known. What is it? Well, since it's being assigned from x, which is a &'a mut u8, it should also be a &'a mut u8. Note that this is not following the "shortest lifetime possible" rule of lifetime elision. You didn't elide a lifetime, you elided the whole type, which is reconstructed by type inference.
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until its use at the end
let y: &'a mut u8 = x;
x;
}
}
Well, that's no good. Since y has the same lifetime as x, its creation involves moving the reference in x and making x invalid. The program is thus rejected for trying to use x.
Adding the signature to y essentially gives the compiler a new place where it can infer lifetimes. Before, normal type inference made y have the same type as x, which meant it lasted as long as x and made x unusable. Now, y doesn't need to have the same type as x; the lifetime of the borrow can be different. In particular, it is made shorter.
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until it's use at the end
'b: {
let y: &'b mut u8 = x; // y and x can now have different lifetimes, *x is reborrowed here
}
x; // x not moved from, still valid
}
}
Now, instead of moving the reference x into y and making it invalid, the value *x is temporarily "reborrowed" to make y, as by let y: &'b mut u8 = &'b mut *x.
The other possible fix is to explicitly say "borrow *x again with a different lifetime":
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y = &mut *x;
x;
}
The principle is the same as before: saying & more often gives the compiler more places where it can massage the lifetimes in the program to make everything work.
This code works fine (Playground):
struct F<'a> {
x: &'a i32,
}
impl<'a> F<'a> {
fn get<'b>(&'b self) -> &'a i32 {
self.x
}
}
fn main() {
let x = 3;
let y = F { x: &x };
let z = y.get();
}
But when I change x to be a mutable reference instead (Playground):
struct Foo<'a> {
x: &'a mut i32, // <-- `mut` added
}
impl<'a> Foo<'a> {
fn get(&self) -> &'a i32 {
self.x
}
}
fn main() {
let mut x = 3; // <-- `mut` added
let y = Foo { x: &mut x }; // <-- `mut` added
let z = y.get();
}
I get this error:
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:7:9
|
7 | self.x
| ^^^^^^
|
note: ...the reference is valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> Foo<'a> {
| ^^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
--> src/main.rs:6:5
|
6 | / fn get(&self) -> &'a i32 {
7 | | self.x
8 | | }
| |_____^
Why does that happen? As far as I see it, nothing about the lifetimes has changed: all values/references still live exactly as long as in the first code snippet.
Why does the Rust compiler reject this implementation of get? Because it allows:
The following is a perfectly reasonable main, assuming that get compiles:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
Yet if get were to compile, this would be fine:
a does not borrow y because the lifetime is different
b "consumes" y (moving from y.x) but we do not reuse it after
So everything is fine, except that we now have a &i32 and &mut i32 both pointing to x.
Note: to make it compile, you can use unsafe inside of get: unsafe { std::mem::transmute(&*self.x) }; scary, eh?
At the heart of the borrow-checking algorithm is the cornerstone on which Rust's memory safety is built:
Aliasing XOR Mutability
Rust achieves memory safety without garbage collection by guaranteeing that whenever you are modifying something, no observer can have a reference inside that something that could become dangling.
This, in turns, lets us interpret:
&T as an aliasing reference; it is Copy
&mut T as a unique reference; it is NOT Copy, as it would violate uniqueness, but it can be moved
This difference saved us here.
Since &mut T cannot be copied, the only way to go from &mut T to &T (or &mut T) is to perform a re-borrowing: dereference and take a reference to the result.
This is done implicitly by the compiler. Doing it manually makes for a somewhat better error message:
fn get<'b>(&'b self) -> &'a i32 {
&*self.x
}
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:7:9
|
7 | &*self.x
| ^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn get(&'a self) -> &'a i32
--> <anon>:6:5
|
6 | fn get<'b>(&'b self) -> &'a i32 {
| ^
Why cannot it infer a lifetime? Because lifetime of the re-borrow is limited by 'b but we are requiring a 'a and there's no relationship between the two!
By the way, this is what is saving us from blunder here, because it ensures that the instance Foo must be borrowed while the result lives (preventing us to use a mutable reference via Foo::x).
Following the compiler hint, and returning &'b i32 works... and prevents the above main from compiling:
impl<'a> Foo<'a> {
fn get<'b>(&'b self) -> &'b i32 {
&*self.x
}
}
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
error[E0505]: cannot move out of `y.x` because it is borrowed
--> <anon>:16:9
|
15 | let a = y.get();
| - borrow of `y` occurs here
16 | let b = y.x;
| ^ move out of `y.x` occurs here
However it lets the first main compile without issue:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let z = y.get();
println!("{}", z);
}
Prints 3.
This code works fine (Playground):
struct F<'a> {
x: &'a i32,
}
impl<'a> F<'a> {
fn get<'b>(&'b self) -> &'a i32 {
self.x
}
}
fn main() {
let x = 3;
let y = F { x: &x };
let z = y.get();
}
But when I change x to be a mutable reference instead (Playground):
struct Foo<'a> {
x: &'a mut i32, // <-- `mut` added
}
impl<'a> Foo<'a> {
fn get(&self) -> &'a i32 {
self.x
}
}
fn main() {
let mut x = 3; // <-- `mut` added
let y = Foo { x: &mut x }; // <-- `mut` added
let z = y.get();
}
I get this error:
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:7:9
|
7 | self.x
| ^^^^^^
|
note: ...the reference is valid for the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> Foo<'a> {
| ^^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
--> src/main.rs:6:5
|
6 | / fn get(&self) -> &'a i32 {
7 | | self.x
8 | | }
| |_____^
Why does that happen? As far as I see it, nothing about the lifetimes has changed: all values/references still live exactly as long as in the first code snippet.
Why does the Rust compiler reject this implementation of get? Because it allows:
The following is a perfectly reasonable main, assuming that get compiles:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
Yet if get were to compile, this would be fine:
a does not borrow y because the lifetime is different
b "consumes" y (moving from y.x) but we do not reuse it after
So everything is fine, except that we now have a &i32 and &mut i32 both pointing to x.
Note: to make it compile, you can use unsafe inside of get: unsafe { std::mem::transmute(&*self.x) }; scary, eh?
At the heart of the borrow-checking algorithm is the cornerstone on which Rust's memory safety is built:
Aliasing XOR Mutability
Rust achieves memory safety without garbage collection by guaranteeing that whenever you are modifying something, no observer can have a reference inside that something that could become dangling.
This, in turns, lets us interpret:
&T as an aliasing reference; it is Copy
&mut T as a unique reference; it is NOT Copy, as it would violate uniqueness, but it can be moved
This difference saved us here.
Since &mut T cannot be copied, the only way to go from &mut T to &T (or &mut T) is to perform a re-borrowing: dereference and take a reference to the result.
This is done implicitly by the compiler. Doing it manually makes for a somewhat better error message:
fn get<'b>(&'b self) -> &'a i32 {
&*self.x
}
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:7:9
|
7 | &*self.x
| ^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn get(&'a self) -> &'a i32
--> <anon>:6:5
|
6 | fn get<'b>(&'b self) -> &'a i32 {
| ^
Why cannot it infer a lifetime? Because lifetime of the re-borrow is limited by 'b but we are requiring a 'a and there's no relationship between the two!
By the way, this is what is saving us from blunder here, because it ensures that the instance Foo must be borrowed while the result lives (preventing us to use a mutable reference via Foo::x).
Following the compiler hint, and returning &'b i32 works... and prevents the above main from compiling:
impl<'a> Foo<'a> {
fn get<'b>(&'b self) -> &'b i32 {
&*self.x
}
}
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let a = y.get();
let b = y.x;
println!("{} {}", a, b);
}
error[E0505]: cannot move out of `y.x` because it is borrowed
--> <anon>:16:9
|
15 | let a = y.get();
| - borrow of `y` occurs here
16 | let b = y.x;
| ^ move out of `y.x` occurs here
However it lets the first main compile without issue:
fn main() {
let mut x = 3;
let y = Foo { x: &mut x };
let z = y.get();
println!("{}", z);
}
Prints 3.