This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Closed 18 days ago.
According to my understanding, next needs a &mut Test, but create_test() returns a Test.
Why can this be compiled?
My guess is that . will implicitly convert Test to &mut Test, I am not sure. Can somebody explain more about this?
pub struct Test {
t: u64,
}
fn create_test() -> Test {
Test {
t: 1
}
}
impl Test {
pub fn next(&mut self) {
self.t = 10;
}
}
fn main() {
let mut t = Test { t: 20 };
t.next();
create_test().next(); // here
}
This is explained in the Method-call expressions section of the book.
When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method.
This is exactly what is happening here. The rust compiler is automatically borrowing value returned create_test.
Related
This question already has answers here:
Why can't I reuse a &mut reference after passing it to a function that accepts a generic type?
(1 answer)
Why does creating a mutable reference to a dereferenced mutable reference work?
(3 answers)
Do all primitive types implement the Copy trait?
(1 answer)
Closed 1 year ago.
Consider this code:
struct A;
trait Test {
fn test(self);
}
impl Test for &mut A {
fn test(self) {
println!("&mut Test called");
}
}
fn test(a: &mut A) {
a.test();
}
fn test2(a: impl Test) {
a.test();
}
fn main() {
let mut a = A;
let a_mut_ref = &mut a;
test(a_mut_ref); // works fine
test(a_mut_ref); // works fine
test2(a_mut_ref); // `a_mut_ref` moved here? Why?
test2(a_mut_ref); // compile error `use of moved value` here
}
According to Rust's docs, mutable references do not implement Copy.
Why does calling test twice work fine?
Why does not it work with test2 the same way?
How can I change test2 to keep both impl-like boundary and get successful compilation?
This question already has answers here:
Is there a way to make an immutable reference mutable?
(2 answers)
Why is transmuting &T to &mut T Undefined Behaviour?
(2 answers)
How to avoid writing duplicate accessor functions for mutable and immutable references in Rust?
(4 answers)
Closed 2 years ago.
I have a custom iterator which reads data from a reference to a Vec in a non-contiguous manner. It will never return two references to the same memory, so I believe it is safe to implement a mutable counterpart.
However, the logic for the iterator itself is quite complex, and it would be entirely identical for the mutable version. In an attempt to avoid code duplication, I use my non-mut iterator under the hood, and then cast the result to add mutability. This works as expected, but I am unsure if it's invoking some kind of undefined behavior.
pub mod lib {
pub struct Data {
pub v: Vec<u64>,
}
impl Data {
pub fn iter(&self) -> MyIter {
MyIter {
data: &self.v,
i: 0,
}
}
pub fn iter_mut(&mut self) -> MyIterMut {
MyIterMut { iter: self.iter() }
}
}
pub struct MyIter<'a> {
data: &'a [u64],
i: usize,
}
impl<'a> Iterator for MyIter<'a> {
type Item = &'a u64;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.data.len() {
return None;
}
let res = &self.data[self.i];
self.i += 1;
Some(res)
}
}
pub struct MyIterMut<'a> {
iter: MyIter<'a>,
}
impl<'a> Iterator for MyIterMut<'a> {
type Item = &'a mut u64;
fn next(&mut self) -> Option<Self::Item> {
unsafe { std::mem::transmute(self.iter.next()) }
}
}
}
fn main() {
let mut d = lib::Data { v: vec![0; 8] };
for elem in d.iter_mut() {
*elem = 123;
}
println!("{:?}", d.v);
}
Complete working example
The mutable iterator is only constructed in the iter_mut method. This means the initial value will always start as a mutable variable, due to the &mut self. It wouldn't be possible to construct this mutable iterator from an immutable variable.
In C++, often times you will use a const_cast to avoid duplicating an implementation that only varies in constness.
Is this something I can do in Rust?
If MyIter contains an immutable reference to the original vec, then you can't transmute, as you could have multiple instances of MyIter, leading to conflicting references. It seems like the duplicate crate could be of use here, providing an easy way to duplicate code with slight differences.
This question already has answers here:
Is it possible to create a wrapper around an &mut that acts like an &mut
(1 answer)
Why is the mutable reference not moved here?
(4 answers)
Closed 2 years ago.
I've been adapting some old code I wrote, one of them had the following (simplified):
pub fn a(x: &mut i32) {
for i in 0..10 {
b(x);
}
}
pub fn b(_x: &mut i32) {
}
which worked fine, even though &mut i32 isn't Copy.
I wanted to restrict what methods could be called on the underlying type, (as instead of &mut i32 I had something along the lines of &mut Vec<...>), so I created a wrapper type over the mutable reference:
#[derive(Debug)]
pub struct I32RefMut<'a>(&'a mut i32);
And I attempted to rewrite a and b using this wrapper as follows:
pub fn a2(x: I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: I32RefMut) {
}
This gives the following error
17 | pub fn a2(x: I32RefMut) {
| - move occurs because `x` has type `I32RefMut<'_>`, which does not implement the `Copy` trait
18 | for _i in 0..10 {
19 | b2(x);
| ^ value moved here, in previous iteration of loop
Playground link
Which is understandable, as x gets moved into b2 on the first iteration of the loop.
Unfortunately I cannot implement Clone nor Copy, as there may only be 1 mutable reference to the object at a time.
My question is how does &mut i32 work around this and how can I implement this workaround (or similar) on my type I32RefMut.
If possible I'd like to avoid unsafe code as much as possible, such as using #[repr(transparent)] struct I32Wrapper(i32) and then transmuting &mut i32 to &mut I32Wrapper, unless a safe wrapper of this type of operation exists already.
EDIT:
Found a "hack" solution, but I'm not very happy about how it looks, so I'll leave the question open. If no other solutions are found, I'll post it as an answer.
If the call to b2 is changed to b2( I32RefMut(x.0) ), then it successfully compiles. This however, cannot be generalised to a function as such:
impl<'a> I32RefMut<'a> {
pub fn my_clone<'b: 'a>(&'b mut self) -> I32RefMut<'b> {
I32RefMut( self.0 )
}
}
As when we try to call it the compiler tells us we can't borrow x mutably twice.
As this wrapper type is supposed to be defined in a library, I cannot expose it's internal reference, as the whole point of the wrapper was to restrain what the user can call on the reference.
The thing is that you are taking ownership of your new type instance when calling b. Just take a reference to your type instead to get access to the underlaying type:
pub fn a2(x: &I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: &I32RefMut) {
}
Playground
Actually if you want to mutate it you need to play around a bit with them:
pub fn a2(mut x: I32RefMut) {
for _i in 0..10 {
b2(&mut x);
}
}
pub fn b2(_x: &mut I32RefMut) {
*(_x.0) += 1
}
Playground
This question already has answers here:
How do I write the lifetimes for references in a type constraint when one of them is a local reference?
(1 answer)
Borrowed value does not live long enough when iterating over a generic value with a lifetime on the function body
(1 answer)
How does "for<>" syntax differ from a regular lifetime bound?
(1 answer)
Closed 4 years ago.
There are lots of similar questions, but I couldn't find the answer to my exact question.
In my Rust code, I have a generic type and want to implement a method that takes a reference to another instance of the that type, and then another method that consumes its argument but does exactly the same thing as the first one:
#[derive(Debug, PartialEq, Clone)]
pub struct Wrapper<T> {
v: T,
}
impl<T> Wrapper<T> {
pub fn f_ref(&self, _other: &Wrapper<T>) { /* ... */ }
pub fn f_consume(&self, other: Wrapper<T>) {
self.f_ref(&other)
}
}
It compiles just fine.
Now I want to do basically the same, but while implementing a trait. First, the function that takes a reference:
use std::ops::AddAssign;
impl<'a, T> AddAssign<&'a Wrapper<T>> for Wrapper<T> where T: AddAssign<&'a T> {
fn add_assign(&mut self, other: &'a Wrapper<T>) {
self.v += &other.v;
}
}
#[test]
fn test() {
let mut a = Wrapper { v: 1_i32 };
let b = Wrapper { v: 2 };
a += &b;
drop(b);
assert_eq!(a, Wrapper { v: 3 });
}
It works, too.
Now I want to implement AddAssign for Wrapper<T> based on the implementation of AddAssign<&Wrapper<T>> that I already have. I understand that if T has references in it, it will cause trouble, so I make sure it has 'static lifetime. I'm OK with it: in my program, I expect T to be something like an owned matrix of numbers wrapped in some custom struct.
impl<'a, T> AddAssign for Wrapper<T> where T: 'static + AddAssign<&'a T>, Wrapper<T>: 'static {
fn add_assign(&mut self, other: Wrapper<T>) {
*self += &other;
}
}
And it fails. The compiler says that other must stay valid after we used a reference to it to in a += expression. But when we used such a reference in the test() function above and dropped b there (which played the role of other here) and used the result later, the compiler agreed it's OK. Why?
I suspect that I need to specify some additional trait bounds for T or Wrapper<T> but don't understand what these bound should be.
Code in playground.
This question already has answers here:
Implementing Index trait to return a value that is not a reference
(2 answers)
Closed 5 years ago.
I want to learn how to use the Index trait for my toy roguelike but can't even get it to work in a useless, dummy scenario.
use std::ops::Index;
// Dummy struct that wraps i32
#[derive(Clone, Copy, Debug)]
pub struct Integer {
pub val: i32,
}
impl Integer {
fn new(num: i32) -> Self {
Integer { val: num }
}
}
// Using the index operator on an Integer should add the index to the Integer's value.
// let i = Integer::new(20);
// i[20];
// The above code should make it so i.val == 40
impl Index<Integer> for Integer {
type Output = i32;
// The error is in the following line:
fn index(&self, to_add: Integer) -> &Self::Output {
self.val + to_add.val;
}
}
// The code causes an error before it reaches this
fn main() {
let mut i = Integer::new(20);
let mut n = Integer::new(30);
println!("i[20] is: {:?}", i[n]);
}
I get this error:
error[E0308]: mismatched types
--> src/main.rs:23:55
|
23 | fn index(&self, to_add: Integer) -> &Self::Output {
| _______________________________________________________^
24 | | self.val + to_add.val;
25 | | }
| |_____^ expected &i32, found ()
|
= note: expected type `&i32`
found type `()`
I don't really know what I'm talking about but I guess that the value dies before it reaches the end of the function or something like that? I don't yet fully understand lifetimes.
I know this looks like a "NO IDEA WHAT IM DOING FIX PLS" question, but I'd love to know what I'm doing wrong here so I can learn from it.
Editor's note: This answer applied to the original question before the OP completely changed it. It is no longer applicable to the posted question.
The Index documentation says, emphasis mine:
The Index trait is used to specify the functionality of indexing operations like container[index] when used in an immutable context.
You are attempting to mutate the value, which is simply not possible. You can also tell this from the signature of index:
pub trait Index<Idx>
where
Idx: ?Sized,
{
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}
There's no mut anywhere here; you cannot "implement" a trait with a completely different signature! You also cannot change the type of one of the arguments (in this case, self).
Bluntly put, Index is the wrong trait to use. Additionally, idiomatic Rust users would be really upset if you did implement the code this way; we generally aren't of the "reuse an operator for a completely different meaning" crowd.
Instead, this should just be a function with a name:
impl Integer {
fn increment(&mut self, to_add: i32) {
self.val += to_add;
}
}
Alternatively, you could implement DerefMut:
use std::ops::{Deref, DerefMut};
impl Deref for Integer {
type Target = i32;
fn deref(&self) -> &Self::Target { &self.val }
}
impl DerefMut for Integer {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.val }
}
And then use it like
let mut i = Integer::new(20);
*i += 20;
println!("i[20] is: {:?}", i);