rust


error: cannot move out of borrowed content on &mut self


I was trying to make a Disjoint-Set data structure in Rust. The relevant code is:
pub struct Set<'a, T: 'a> {
rank: u32,
value: T,
parent: Option<&'a mut Set<'a, T>>
}
impl<'a, T> Set<'a, T> {
pub fn find(&'a mut self) -> &'a mut Set<'a, T> {
match self.parent {
None => self,
Some(mut p) => {
self.parent = Some( p.find() );
self.parent.unwrap()
}
}
}
}
The errors I get are:
lib.rs:69:15: 69:19 error: cannot move out of borrowed content
lib.rs:69 match self.parent {
^~~~
lib.rs:73:17: 73:21 error: cannot move out of borrowed content
lib.rs:73 self.parent.unwrap()
^~~~
I'm fairly new to Rust and I'm not sure I understand the borrow checker fully, but I am using references to avoid taking ownership of structs themselves so that they can be pointed to and reassigned similar to how you would in other languages.
I can avoid these errors by removing the mut from the references in the struct, but then I cannot change the parent of each set because they are immutable.
I have read through similar questions such as:
Rust: “cannot move out of self because it is borrowed” error
Can't borrow File from &mut self (error msg: cannot move out of borrowed content)
But these aren't helping me work out how to solve this issue. I have also tried restructuring the function find as well as the struct itself to use Rc<RefCell<Set>> and Box<Set> but I always end up at the same error.
Can anyone help me understand this error and how to fix it?
I am using rustc 1.0.0-nightly (44a287e6e 2015-01-08)
By default, a match arm is going to take the enum variant components by value. Since your type isn't copyable, that would mean that the component would be moved out of the original place. This would make your original struct partially undefined - a big no-no in Rust.
To fix that, take a reference instead, as the compiler instructs.
Next up, instead of storing the result in an Option and then immediately taking it back out, try to keep the reference in a variable, put it in the Option and return it:
let z = p.find();
self.parent = Some(z);
z
This leads to the core problem with the whole idea:
error: cannot borrow `*z` as mutable more than once at a time
You are trying to store a mutable reference and return it. This would mean that there would be multiple concurrent mutable references to the same item (also known as aliasing). Preventing this is another core tenet of Rust's safety systems, because then it's harder for the compiler to guarantee when and where things are being changed.

Related Links

How can I optimize reading a UTF-8 string from a file with a known offset and size?
Create vector of objects implementing a trait in Rust
Using loop variable from “..” loop causes type conversion?
What is RFC 401's coerce_inner useful for?
Rust Borrow checker only complains about borrowing as mutable multiple times when a function that returns a reference with the same lifetime assigned
How can I remove `let _ : () = …`?
Does if-let with a pair short-circuit?
Rust borrow lasts beyond the scope it's in?
How can I include an arbitrary set of Protobuf-built files without knowing their names?
Specialization of method in inherent impl
Getting reference to object behind Rc
Similar implementations of one trait for many structs
Unable to find unsafe trait implementation
Injecting a Diesel connection into an Iron middleware
Rust function does not have static lifetime?
Can Rust optimise away the bit-wise copy during move of an object someday?

Categories

HOME
knockout.js
libgdx
class
opencart
xcode8.1
barcode-scanner
applescript
dry
plaid
filesize
bing-search
drag-and-drop
google-search-console
fedora
driver
scrape
match
cqrs
watch-os-3
smartgwt
webstore
jpa-2.0
mahout-recommender
twisted
google-cloud-logging
vertica
susy-sass
boomi
coroutine
spam
opam
jitsi
backtracking
acl
firemonkey-style
nurbs
unordered-multimap
introspection
ipa
hevc
pyspark-sql
tsung
bitbake
fusion
source-insight
windows2012
delayed-job
osx-lion
android-collapsingtoolbar
nest
bean-validation
buildforge
textmate2
numerics
redgate
jade4j
llvm-ir
widestring
suds
grails3.2.0
cloudera-sentry
opal-framework
google-prediction
jenkins-slave
intellij-lombok-plugin
uiautomatorviewer
watir-webdriver
gtk#
annotatorjs
boost-compute
elastic4s
xmlbeans
clp
svnserve
wininet
eclemma
yii2-model
vaadin4spring
textblock
gwt-syncproxy
place
supersocket.net
green-threads
artisan
kotlin-android-extensions
prism-4
nssortdescriptor
htmltidy
maven-shade-plugin
mod-auth-openidc
flurry-analytics
quantify
air-native-extension
preorder
proxy-server
progress-db
frontbase
unrealscript
postgres-xc
jacob
unicoins
web-frameworks
itunes-sdk
system-requirements
android-dialog
first-class
struts2-s2hibernate
gamesalad
prefuse
algol68
quartz-core
office-automation
css-friendly
dip
turbine
aptitude
ccnet-config
pinax
gtktextview
sqlsitemapprovider
iphone-sdk-3.1.3
jboss-mdb
error-detection

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App