No puede sobrecargar el operador agregar en una estructura que contiene una vaca porque no puedo devolver el valor que hace referencia a los datos locales -- rust camp Relacionados El problema

Cannot overload add operator on a struct containing a Cow because I cannot return value referencing local data


0
vote

problema

Español

Estoy implementando operaciones básicas para matrices en un campo genérico F . Al hacerlo, quiero sobrecargar el operador Agregar para el tipo de matriz. El tipo de matriz contiene un Cow poseer o préstamo F . Quiero que la suma de matriz resultante tome prestado el F de la matriz agregada independientemente de si posee o toma prestaciones F .

El compilador se queja de devolver una referencia creada dentro de la función, pero no entiendo por qué. Me parece que estoy haciendo referencia a un argumento de entrada de la función y no los datos creados localmente. Aquí está mi ejemplo mínimo:

  use std::{     borrow::{Borrow, Cow},     ops::Add, };  pub trait Field {     type FElt: Copy + Eq;      fn zero(&self) -> Self::FElt;     fn add(&self, a: Self::FElt, b: Self::FElt) -> Self::FElt; }  pub struct Mat<'a, F: Clone + Eq + Field> {     field: Cow<'a, F>,     rows: usize,     cols: usize,     data: Vec<F::FElt>, }  impl<'a, F: Clone + Eq + Field> Mat<'a, F> {     pub fn zero(field: &'a F, rows: usize, cols: usize) -> Self {         if rows == 0 || cols == 0 {             panic!("Empty matrix");         }          Self {             field: Cow::Borrowed(field),             rows,             cols,             data: vec![field.zero(); rows * cols],         }     } }  impl<'a, F: Clone + Eq + Field> Add for Mat<'a, F> {     type Output = Self;      fn add(self, other: Self) -> Self::Output {         if self.field != other.field {             panic!("Cannot add matrices: fields do not match");         }         if self.rows != other.rows || self.cols != other.cols {             panic!("Cannot add matrices: dimensions do not match");         }          let f: &F = self.field.borrow();         let mut sum = Mat::zero(f, self.rows, self.cols);         for i in 0..self.rows * self.cols {             sum.data[i] = f.add(self.data[i], other.data[i]);         }         sum     } }  fn main() {}   

Aquí está el error que recibo:

  error[E0515]: cannot return value referencing local data `self.field`   --> src/main.rs:51:9    | 46 |         let f: &F = self.field.borrow();    |                     ---------- `self.field` is borrowed here ... 51 |         sum    |         ^^^ returns a value referencing data owned by the current function   
Original en ingles

I'm implementing basic operations for matrices on a generic field F. In doing so, I want to overload the add operator for the matrix type. The matrix type contains a Cow either owning or borrowing F. I want the resulting matrix sum to borrow the F of the added matrix regardless if it owns or borrows F.

The compiler complains that I return a reference created inside the function, but I don't understand why. It seems to me I'm referencing an input argument of the function and not data created locally. Here's my minimal example:

use std::{     borrow::{Borrow, Cow},     ops::Add, };  pub trait Field {     type FElt: Copy + Eq;      fn zero(&self) -> Self::FElt;     fn add(&self, a: Self::FElt, b: Self::FElt) -> Self::FElt; }  pub struct Mat<'a, F: Clone + Eq + Field> {     field: Cow<'a, F>,     rows: usize,     cols: usize,     data: Vec<F::FElt>, }  impl<'a, F: Clone + Eq + Field> Mat<'a, F> {     pub fn zero(field: &'a F, rows: usize, cols: usize) -> Self {         if rows == 0 || cols == 0 {             panic!("Empty matrix");         }          Self {             field: Cow::Borrowed(field),             rows,             cols,             data: vec![field.zero(); rows * cols],         }     } }  impl<'a, F: Clone + Eq + Field> Add for Mat<'a, F> {     type Output = Self;      fn add(self, other: Self) -> Self::Output {         if self.field != other.field {             panic!("Cannot add matrices: fields do not match");         }         if self.rows != other.rows || self.cols != other.cols {             panic!("Cannot add matrices: dimensions do not match");         }          let f: &F = self.field.borrow();         let mut sum = Mat::zero(f, self.rows, self.cols);         for i in 0..self.rows * self.cols {             sum.data[i] = f.add(self.data[i], other.data[i]);         }         sum     } }  fn main() {} 

Here's the error I'm getting:

error[E0515]: cannot return value referencing local data `self.field`   --> src/main.rs:51:9    | 46 |         let f: &F = self.field.borrow();    |                     ---------- `self.field` is borrowed here ... 51 |         sum    |         ^^^ returns a value referencing data owned by the current function 
  
   
   

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

Me parece que estoy haciendo referencia a un argumento de entrada de la función y no los datos creados localmente.

self no se ha creado localmente, pero se mueve en el método add (que toma self ), por lo que aún se destruirá cuando se devuelva la función. Si la salida se le permitió hacer referencia a ella, la referencia se volvería colgando tan pronto como la función regresó.

Si desea que la salida tome prestado de la entrada, debe tomar la entrada como referencia, lo que significa implementar Add para &'b Mat<'a, F> en lugar de Mat<'a, F> < / Código>. Consulte ¿Cómo implemento el rasgo Agregar para una referencia a una estructura? Tenga en cuenta que el Output6 El tipo debe ser Mat<'b, F> en lugar de Mat<'a, F> .

Hay otra solución más simple para el problema como se plantea. El préstamo no funciona porque el Cow estaba en la función. ¿Por qué no simplemente moverlo de nuevo? Una forma fácil de hacerlo es modificar add0 y devuélvalo en lugar de crear add11111 dentro de la función.

  add2  

¡No solo evita un clon de Output13 , sino que también reúne add4 's buffer de esta manera.

 

It seems to me I'm referencing an input argument of the function and not data created locally.

self may not have been created locally, but it is moved into the add method (which takes self), so it will still be destroyed when the function returns. If the output were allowed to reference it, the reference would become dangling as soon as the function returned.

If you want the output to borrow from the input, you must take the input as a reference, which means implementing Add for &'b Mat<'a, F> instead of Mat<'a, F>. See How do I implement the Add trait for a reference to a struct? Note that the Output type must be Mat<'b, F> instead of Mat<'a, F>.

There's another, simpler solution for the problem as posed. Borrowing doesn't work because the Cow was mooved in to the function. Why not just move it back out? An easy way to do this is to modify self and return it rather than creating sum inside the function.

    fn add(mut self, other: Self) -> Self::Output {         /* ... */          for i in 0..self.rows * self.cols {             self.data[i] = self.field.add(self.data[i], other.data[i]);         }         self     } 

Not only do you avoid a potentially expensive clone of field, but you also reuse data's buffer this way.

 
 
         
         

Relacionados problema

3  ¿Cómo coincidir para una opción con campos múltiples?  ( How to match for an option with multiple fields ) 
¿Cómo igualo a una opción con múltiples campos? Tengo el siguiente código: let opt_windowrecv = glfw_context.create_window(1280, 720, "Hello World!", glfw:...

4  Anexar la cadena, no puede salir de la distensión de '&' Pointer  ( String append cannot move out of dereference of pointer ) 
Estoy teniendo problemas para combinar dos cuerdas, soy muy nuevo en óxido, así que si hay una manera más fácil de hacer esto, no dude en mostrarme. My Func...

8  ¿Por qué todos los índices están en óxido de tipo de uso?  ( Why are all indexes in rust of type usize ) 
óxico std::ops::Index<T> solo Admite T siendo un usize . ¿Cuál es la razón detrás de esto? Además, no hay consejos para "intentar usar usando" cuando...

4  ¿Es cierto que para todos los tipos `t`,` u` si 't` está coaccionado a `u` entonces` & t` es coaccionado para `& u`?  ( Is it true that for all types t u if t is coerced to u then t is coe ) 
es bien documentado que [T; n] puede coaccionar a [T] . El siguiente código también es Si 99887776611111 está obligado a import re dset = [] text = ...

0  ¿Cómo puedo eliminar la variable mutable en esta función de MandelBrot sin recursión?  ( How can i remove the mutable variable in this mandelbrot function without recurs ) 
La siguiente función calcula el número de órbitas que lleva a una Monelbrot Fractal Valor inicial para " Escape ": extern crate num; fn mandel_escape(x:...

6  ¿Cómo actualizar o insertar en un VEC?  ( How to update or insert on a vec ) 
Estoy escribiendo una estructura de datos en óxido. Contiene un Vec de pares de valor clave. Cuando se inserta en la estructura, necesito encontrar una clav...

1  Moviéndose y devolviendo un puntero mutable  ( Moving and returning a mutable pointer ) 
Estoy trabajando a través de este tutorial de óxido , y estoy tratando de Resuelve este problema: Implementar una función, incrementMut que toma como in...

0  ¡Cómo pasar un token de visibilidad a los Bitflags! ¿macro?  ( How to pass a visibility token to the bitflags macro ) 
Estoy usando el bitflags caja. Quiero generar automáticamente algunas otras implementaciones para mis tipos, así que intenté llamar a la macro 9988776662 ...

5  Implementar FMT :: PANTALLA PARA VEC <T>  ( Implement fmtdisplay for vect ) 
Quiero implementar el fmt::Display para una estructura anidada comúnmente utilizada en mi código. // The root structure pub struct WhisperFile<'a> { ...

8  Tratar con las relaciones problemáticas de padres e hijos aplicadas por C FFI  ( Dealing with problematic parent child relationships enforced by c ffi ) 
Tengo una biblioteca C con una interfaz similar a esta: (He representado a la API C dentro de la óxida, de modo que todo el código en esta pregunta se pueda c...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos