Repository: GuillaumeGomez/rust-GSL (language: rust)

Issue:
Some `MultiFitFSolver` methods returns a `VectorF64` object with no lifetime bound 
Whereas the returned objects should not live longer than `MultiFitFSolver`.


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index b3ebc4bb..3f77132b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,13 +18,14 @@
 extern crate gsl_sys as sys;
 extern crate paste;
 
-pub use types::*;
+pub use self::types::*;
 
-pub use elementary::Elementary;
-pub use pow::Pow;
-pub use trigonometric::Trigonometric;
-pub use types::rng;
-pub use utilities::IOStream;
+pub use self::elementary::Elementary;
+pub use self::pow::Pow;
+pub use self::trigonometric::Trigonometric;
+pub use self::types::rng;
+pub use self::utilities::IOStream;
+pub use self::view::View;
 
 // enums part
 pub use self::enums::*;
@@ -32,6 +33,7 @@ pub use self::enums::*;
 mod enums;
 mod macros;
 mod utilities;
+mod view;
 
 #[doc(hidden)]
 pub mod ffi;
diff --git a/src/types/multifit_solver.rs b/src/types/multifit_solver.rs
index 58399a38..55434810 100644
--- a/src/types/multifit_solver.rs
+++ b/src/types/multifit_solver.rs
@@ -213,10 +213,9 @@ int main(void) {
 ```
 */
 
-use crate::Value;
+use crate::{Value, VectorF64, View};
 use ffi::{self, FFI};
 use std::os::raw::{c_int, c_void};
-use VectorF64;
 
 ffi_wrapper!(MultiFitFSolverType, *mut sys::gsl_multifit_fsolver_type);
 
@@ -285,8 +284,8 @@ impl MultiFitFSolver {
     }
 
     #[doc(alias = "gsl_multifit_fsolver_position")]
-    pub fn position(&self) -> VectorF64 {
-        unsafe { ffi::FFI::wrap(sys::gsl_multifit_fsolver_position(self.unwrap_shared())) }
+    pub fn position(&self) -> View<'_, VectorF64> {
+        unsafe { View::new(sys::gsl_multifit_fsolver_position(self.unwrap_shared())) }
     }
 }
 
@@ -320,24 +319,24 @@ impl MultiFitFdfSolver {
         result_handler!(ret, ())
     }
 
-    pub fn x(&self) -> VectorF64 {
-        unsafe { ffi::FFI::soft_wrap((*self.unwrap_shared()).x) }
+    pub fn x(&self) -> View<'_, VectorF64> {
+        unsafe { View::new((*self.unwrap_shared()).x) }
     }
 
-    pub fn f(&self) -> VectorF64 {
-        unsafe { ffi::FFI::soft_wrap((*self.unwrap_shared()).f) }
+    pub fn f(&self) -> View<'_, VectorF64> {
+        unsafe { View::new((*self.unwrap_shared()).f) }
     }
 
-    pub fn dx(&self) -> VectorF64 {
-        unsafe { ffi::FFI::soft_wrap((*self.unwrap_shared()).dx) }
+    pub fn dx(&self) -> View<'_, VectorF64> {
+        unsafe { View::new((*self.unwrap_shared()).dx) }
     }
 
-    pub fn g(&self) -> VectorF64 {
-        unsafe { ffi::FFI::soft_wrap((*self.unwrap_shared()).g) }
+    pub fn g(&self) -> View<'_, VectorF64> {
+        unsafe { View::new((*self.unwrap_shared()).g) }
     }
 
-    pub fn sqrt_wts(&self) -> VectorF64 {
-        unsafe { ffi::FFI::soft_wrap((*self.unwrap_shared()).sqrt_wts) }
+    pub fn sqrt_wts(&self) -> View<'_, VectorF64> {
+        unsafe { View::new((*self.unwrap_shared()).sqrt_wts) }
     }
 
     #[doc(alias = "gsl_multifit_fdfsolver_name")]
@@ -360,8 +359,8 @@ impl MultiFitFdfSolver {
 
     /// This function returns the current position (i.e. best-fit parameters) s->x of the solver s.
     #[doc(alias = "gsl_multifit_fdfsolver_position")]
-    pub fn position(&self) -> VectorF64 {
-        unsafe { ffi::FFI::wrap(sys::gsl_multifit_fdfsolver_position(self.unwrap_shared())) }
+    pub fn position(&self) -> View<'_, VectorF64> {
+        unsafe { View::new(sys::gsl_multifit_fdfsolver_position(self.unwrap_shared())) }
     }
 
     /// These functions iterate the solver s for a maximum of maxiter iterations. After each
diff --git a/src/types/multiroot.rs b/src/types/multiroot.rs
index b5a884e1..41590537 100644
--- a/src/types/multiroot.rs
+++ b/src/types/multiroot.rs
@@ -56,7 +56,7 @@ The state for solvers which do not use an analytic Jacobian matrix is held in a
 The algorithms estimate the matrix J or J^{-1} by approximate methods.
 !*/
 
-use crate::{Value, VectorF64};
+use crate::{Value, VectorF64, View};
 use ffi::FFI;
 use sys;
 use sys::libc::{c_int, c_void};
@@ -217,21 +217,21 @@ impl<'a> MultiRootFSolver<'a> {
 
     /// This function returns the current estimate of the root for the solver `s`, given by `s->x`.
     #[doc(alias = "gsl_multiroot_fsolver_root")]
-    pub fn root(&self) -> VectorF64 {
-        VectorF64::soft_wrap(unsafe { sys::gsl_multiroot_fsolver_root(self.unwrap_shared()) })
+    pub fn root(&self) -> View<'_, VectorF64> {
+        unsafe { View::new(sys::gsl_multiroot_fsolver_root(self.unwrap_shared())) }
     }
 
     /// This function returns the last step `dx` taken by the solver `s`, given by `s->dx`.
     #[doc(alias = "gsl_multiroot_fsolver_dx")]
-    pub fn dx(&self) -> VectorF64 {
-        VectorF64::soft_wrap(unsafe { sys::gsl_multiroot_fsolver_dx(self.unwrap_shared()) })
+    pub fn dx(&self) -> View<'_, VectorF64> {
+        unsafe { View::new(sys::gsl_multiroot_fsolver_dx(self.unwrap_shared())) }
     }
 
     /// This function returns the function value `f(x)` at the current estimate of the root for
     /// the solver `s`, given by `s->f`.
     #[doc(alias = "gsl_multiroot_fsolver_f")]
-    pub fn f(&self) -> VectorF64 {
-        VectorF64::soft_wrap(unsafe { sys::gsl_multiroot_fsolver_f(self.unwrap_shared()) })
+    pub fn f(&self) -> View<'_, VectorF64> {
+        unsafe { View::new(sys::gsl_multiroot_fsolver_f(self.unwrap_shared())) }
     }
 }
 
diff --git a/src/view.rs b/src/view.rs
new file mode 100644
index 00000000..490d7a0a
--- /dev/null
+++ b/src/view.rs
@@ -0,0 +1,33 @@
+//
+// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
+//
+
+use crate::ffi::FFI;
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+/// A struct which binds a type to a lifetime and prevent mutable access.
+pub struct View<'a, T> {
+    inner: T,
+    phantom: PhantomData<&'a ()>,
+}
+
+impl<'a, T> View<'a, T> {
+    pub(crate) fn new<P>(inner: *mut P) -> Self
+    where
+        T: FFI<P>,
+    {
+        Self {
+            inner: FFI::soft_wrap(inner),
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<'a, T> Deref for View<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}


Test patch: