Closed
Description
Consider this piece of code:
struct S1<T> { s: Option<T> }
//struct S1<T> { s: *mut T }
struct Foo<'a> {
bar: S1<&'a str>
}
impl<'a> Foo<'a> {
pub fn new() -> Foo<'a> { // '
Foo { bar: S1 { s: None } }
//Foo { bar: S1 { s: std::ptr::null_mut() } }
}
pub fn baz(&'a self) -> Option<int> {
None
}
pub fn qux(&'a mut self, retry: bool) {
let opt = self.baz();
if retry { self.qux(false); }
}
}
pub fn main() {
let mut foo = Foo::new();
foo.qux(true);
}
It compiles. However, if you change S1
definition to the commented one:
//struct S1<T> { s: Option<T> }
struct S1<T> { s: *mut T }
struct Foo<'a> {
bar: S1<&'a str>
}
impl<'a> Foo<'a> {
pub fn new() -> Foo<'a> { // '
//Foo { bar: S1 { s: None } }
Foo { bar: S1 { s: std::ptr::null_mut() } }
}
pub fn baz(&'a self) -> Option<int> {
None
}
pub fn qux(&'a mut self, retry: bool) {
let opt = self.baz();
if retry { self.qux(false); }
}
}
pub fn main() {
let mut foo = Foo::new();
foo.qux(true);
}
it stops compiling with borrow checking error (and very weird one):
<anon>:20:20: 20:24 error: cannot borrow `*self` as mutable because it is also borrowed as immutable
<anon>:20 if retry { self.qux(false); }
^~~~
<anon>:19:19: 19:23 note: previous borrow of `*self` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*self` until the borrow ends
<anon>:19 let opt = self.baz();
^~~~
<anon>:21:6: 21:6 note: previous borrow ends here
<anon>:18 pub fn qux(&'a mut self, retry: bool) {
<anon>:19 let opt = self.baz();
<anon>:20 if retry { self.qux(false); }
<anon>:21 }
^
error: aborting due to previous error
Originally discovered in this Stackoverflow question. It is much more confusing there because Vec
and HashMap
instead of custom structure are used.
cc @nikomatsakis (right?)