¿Por qué recibo el mensaje “no se puede mover fuera de … porque está prestado” aunque no se hace referencia a ningún dato?
struct Population<'a> {
dat: Vec<genotype<'a>>,
}
impl<'a> Population<'a> {
fn new(dat: Vec<genotype<'a>>) -> Self {
Population { dat }
}
fn select(&self) -> Genotype<'a> {
self.dat.first().unwrap().clone()
}
}
#[derive(Clone)]
struct Genotype<'a> {
data: &'a str,
}
impl<'a> Genotype<'a> {
fn new(data: &'a str) -> Self {
Genotype { data }
}
}
fn main() {
let hello = "Hello World";
let genotype = Genotype::new(hello);
let mut population = Population::new(vec![genotype]);
let other = population.select();
drop(population);
println!("{}", other.data);
}
El compilador indica que no se puede descartar population
porque está siendo prestado en other
:
error[E0505]: cannot move out of `population` because it is borrowed
--> src/main.rs:32:10
|
31 | let other = population.select();
| ------------------- borrow of `population` occurs here
32 | drop(population);
| ^^^^^^^^^^ move out of `population` occurs here
33 | println!("{}", other.data);
| ---------- borrow later used here
No entiendo cómo ambas variables están relacionadas entre sí. Sospecho que el error está en la función select
ya que aparentemente es la fuente del préstamo.
He intentado agregar un lifetime separado a select
(fn select<'b>(&self) -> Genotype<'b>
) pero falla, ya que parece que el compilador asume que el lifetime de la instancia de Population
está de alguna manera vinculado con el Genotype
devuelto, aunque se refiere al &str
interno.
¿Qué estoy haciendo mal exactamente?</genotype<‘a></genotype<‘a>
davy.ai
El problema con el código es que el método
select
devuelve unGenotype
que contiene una referencia a los datos propiedad de la instanciaPopulation
. Cuando llamas aselect()
enpopulation
, estás tomando prestadapopulation
para obtener la referencia a los datos. Esto significa quepopulation
no puede ser eliminada hasta queother
salga de alcance, ya queother
aún tiene una referencia a los datos propiedad depopulation
.Para solucionar el problema, puedes cambiar
select
para que devuelva una copia de los datos deGenotype
en lugar de una referencia. De esta manera, la instancia deGenotype
devuelta porselect
será propietaria de sus datos y no habrá una relación de préstamo entre ella ypopulation
. Así es como puedes modificar el código para hacerlo:Observa que modificamos el método
select
para que devuelvaGenotype
en lugar deGenotype<'a>
, porque el valor devuelto será propietario de sus datos en lugar de tomarlos prestados. Además, cuando llamamos aselect
enmain
, necesitamos llamar aclone
en la instancia deGenotype
devuelta para hacer una copia de sus datos. Esto nos permite eliminarpopulation
sin ningún problema.Con estos cambios, el código ahora se compila sin errores.</genotype<‘a></genotype<‘a>