Pregunta

I have a function that returns a Result<&'a ~Foo, BarErr>, which I can access using:

match x.borrow() {
  Ok(ref foo) => println!("Found {}", foo.value),
  Err(Nope) => println!("Bleh")
}

However, I find myself now in a more complex situation in which I wish to borrow a mutable reference instead, such that I might be able to call a function on it:

match x.borrow() {
  Ok(ref foo) => { foo.inc(); trace!("Found {}", foo.value); },
  Err(Nope) => trace!("Bleh")
}

I've tried a few variations on where I need to stick 'mut' in, such as mut ref foo, ref mut foo, -> mut Result<...>, -> Result, but I can't seem to figure out the syntax required.

I keep getting:

error: cannot borrow immutable dereference of `~`-pointer `***foo` as mutable

What should it be?

Complete code example:

macro_rules! trace(
  ($($arg:tt)*) => (
    { let x = ::std::io::stdout().write_line(format_args!(::std::fmt::format, $($arg)*)); println!("{}", x); }
  );
)

#[deriving(Show)]
struct Foo {
  value: int
}

impl Foo {
  fn inc(&mut self) {
    self.value += 1;
  }
}

#[deriving(Show)]
struct Bar {
  data: Option<~Foo>
}

#[deriving(Show)]
enum BarErr {
  Nope
}

impl Bar {
  fn borrow<'a>(&'a mut self) -> Result<&'a ~Foo, BarErr> {
    match self.data {
      Some(ref e) => return Ok(e),
      None => return Err(Nope)
    }
  }
}

#[test]
fn test_create_indirect() {
  let y = ~Foo { value: 10 };
  let mut x = Bar { data: Some(y) };
  let mut x2 = Bar { data: None };
  {
    match x.borrow() {
      Ok(ref mut foo) => { foo.inc(); trace!("Found {}", foo.value); },
      Err(Nope) => trace!("Bleh")
    }
  }
  {
    let z = x2.borrow();
    trace!("Z: {}", z);
  }
}
¿Fue útil?

Solución

The problem is that references do not own data, hence their mutability is inherited. You cannot turn &'a into &'a mut, because the data under that reference is immutable.

You have to return Result<&'a mut ~Foo, BarErr> in order to achieve what you want:

impl Bar {
  fn borrow<'a>(&'a mut self) -> Result<&'a mut ~Foo, BarErr> {
    match self.data {
      Some(ref mut e) => return Ok(e),
      None => return Err(Nope)
    }
  }
}

#[test]
fn test_create_indirect() {
  let y = ~Foo { value: 10 };
  let mut x = Bar { data: Some(y) };
  let mut x2 = Bar { data: None };
  {
    match x.borrow() {
      Ok(foo) => { foo.inc(); trace!("Found {:?}", foo.value); },
      Err(Nope) => trace!("Bleh")
    }
  }
  {
    let z = x2.borrow();
    trace!("Z: {:?}", z);
  }
}

Note that at the usage site I'm matching x.borrow() against Ok(foo), not Ok(ref mut foo). That's OK because foo itself is &mut, so you can access &mut self methods through it.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top