rust/hg-cpython/src/ancestors.rs
changeset 51255 24d3298189d7
parent 51240 59d81768ad6d
child 51272 c4cbb515b006
equal deleted inserted replaced
51254:f94c10334bcb 51255:24d3298189d7
    58 //
    58 //
    59 // It would be nice for UnsharedPyLeaked to provide this directly as a variant
    59 // It would be nice for UnsharedPyLeaked to provide this directly as a variant
    60 // of the `map` method with a signature such as:
    60 // of the `map` method with a signature such as:
    61 //
    61 //
    62 // ```
    62 // ```
    63 //   unafe fn map_or_err(py: Python,
    63 //   unsafe fn map_or_err(py: Python,
    64 //                       f: impl FnOnce(T) -> Result(U, E),
    64 //                        f: impl FnOnce(T) -> Result(U, E),
    65 //                       convert_err: impl FnOnce(Python, E) -> PyErr)
    65 //                        convert_err: impl FnOnce(Python, E) -> PyErr)
    66 // ```
    66 // ```
    67 //
    67 //
    68 // This would spare users of the `cpython` crate the additional `unsafe` deref
    68 // This would spare users of the `cpython` crate the additional `unsafe` deref
    69 // to inspect the error and return it outside `UnsafePyLeaked`, and the
    69 // to inspect the error and return it outside `UnsafePyLeaked`, and the
    70 // subsequent unwrapping that this function performs.
    70 // subsequent unwrapping that this function performs.
    72     py: Python,
    72     py: Python,
    73     leaked: UnsafePyLeaked<Result<T, E>>,
    73     leaked: UnsafePyLeaked<Result<T, E>>,
    74     convert_err: impl FnOnce(Python, E) -> PyErr,
    74     convert_err: impl FnOnce(Python, E) -> PyErr,
    75 ) -> PyResult<UnsafePyLeaked<T>> {
    75 ) -> PyResult<UnsafePyLeaked<T>> {
    76     // Result.inspect_err is unstable in Rust 1.61
    76     // Result.inspect_err is unstable in Rust 1.61
       
    77     // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
    77     if let Err(e) = *unsafe { leaked.try_borrow(py)? } {
    78     if let Err(e) = *unsafe { leaked.try_borrow(py)? } {
    78         return Err(convert_err(py, e));
    79         return Err(convert_err(py, e));
    79     }
    80     }
       
    81     // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
    80     Ok(unsafe {
    82     Ok(unsafe {
    81         leaked.map(py, |res| {
    83         leaked.map(py, |res| {
    82             res.expect("Error case should have already be treated")
    84             res.expect("Error case should have already be treated")
    83         })
    85         })
    84     })
    86     })
    87 py_class!(pub class AncestorsIterator |py| {
    89 py_class!(pub class AncestorsIterator |py| {
    88     data inner: RefCell<UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>>;
    90     data inner: RefCell<UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>>;
    89 
    91 
    90     def __next__(&self) -> PyResult<Option<PyRevision>> {
    92     def __next__(&self) -> PyResult<Option<PyRevision>> {
    91         let mut leaked = self.inner(py).borrow_mut();
    93         let mut leaked = self.inner(py).borrow_mut();
       
    94         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
    92         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
    95         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
    93         match inner.next() {
    96         match inner.next() {
    94             Some(Err(e)) => Err(GraphError::pynew_from_vcsgraph(py, e)),
    97             Some(Err(e)) => Err(GraphError::pynew_from_vcsgraph(py, e)),
    95             None => Ok(None),
    98             None => Ok(None),
    96             Some(Ok(r)) => Ok(Some(PyRevision(r))),
    99             Some(Ok(r)) => Ok(Some(PyRevision(r))),
    97         }
   100         }
    98     }
   101     }
    99 
   102 
   100     def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
   103     def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
   101         let mut leaked = self.inner(py).borrow_mut();
   104         let mut leaked = self.inner(py).borrow_mut();
       
   105         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   102         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   106         let mut inner = unsafe { leaked.try_borrow_mut(py)? };
   103         inner.contains(rev.0)
   107         inner.contains(rev.0)
   104             .map_err(|e| GraphError::pynew_from_vcsgraph(py, e))
   108             .map_err(|e| GraphError::pynew_from_vcsgraph(py, e))
   105     }
   109     }
   106 
   110 
   134         initrevs: PyObject,
   138         initrevs: PyObject,
   135         stoprev: PyRevision,
   139         stoprev: PyRevision,
   136         inclusive: bool,
   140         inclusive: bool,
   137     ) -> PyResult<AncestorsIterator> {
   141     ) -> PyResult<AncestorsIterator> {
   138         let index = py_rust_index_to_graph(py, index)?;
   142         let index = py_rust_index_to_graph(py, index)?;
       
   143         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   139         let initvec: Vec<_> = {
   144         let initvec: Vec<_> = {
   140             let borrowed_idx = unsafe { index.try_borrow(py)? };
   145             let borrowed_idx = unsafe { index.try_borrow(py)? };
   141             rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
   146             rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
   142         };
   147         };
       
   148         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   143         let res_ait = unsafe {
   149         let res_ait = unsafe {
   144             index.map(py, |idx| {
   150             index.map(py, |idx| {
   145                 VCGAncestorsIterator::new(
   151                 VCGAncestorsIterator::new(
   146                     idx,
   152                     idx,
   147                     initvec.into_iter().map(|r| r.0),
   153                     initvec.into_iter().map(|r| r.0),
   165     data stoprev: PyRevision;
   171     data stoprev: PyRevision;
   166     data inclusive: bool;
   172     data inclusive: bool;
   167 
   173 
   168     def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
   174     def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
   169         let leaked = self.inner(py).borrow();
   175         let leaked = self.inner(py).borrow();
       
   176         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   170         let inner: &RefCell<VCGLazyAncestors<PySharedIndex>> =
   177         let inner: &RefCell<VCGLazyAncestors<PySharedIndex>> =
   171             &*unsafe { leaked.try_borrow(py)? };
   178             &*unsafe { leaked.try_borrow(py)? };
   172         let inner_mut: &mut VCGLazyAncestors<PySharedIndex> =
   179         let inner_mut: &mut VCGLazyAncestors<PySharedIndex> =
   173             &mut *inner.borrow_mut();
   180             &mut *inner.borrow_mut();
   174         inner_mut.contains(rev.0)
   181         inner_mut.contains(rev.0)
   183                                      *self.inclusive(py))
   190                                      *self.inclusive(py))
   184     }
   191     }
   185 
   192 
   186     def __bool__(&self) -> PyResult<bool> {
   193     def __bool__(&self) -> PyResult<bool> {
   187         let leaked = self.inner(py).borrow();
   194         let leaked = self.inner(py).borrow();
       
   195         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   188         let inner = unsafe { leaked.try_borrow(py)? };
   196         let inner = unsafe { leaked.try_borrow(py)? };
   189         let empty = inner.borrow().is_empty();
   197         let empty = inner.borrow().is_empty();
   190         Ok(!empty)
   198         Ok(!empty)
   191     }
   199     }
   192 
   200 
   198         inclusive: bool
   206         inclusive: bool
   199     ) -> PyResult<Self> {
   207     ) -> PyResult<Self> {
   200         let cloned_index = index.clone_ref(py);
   208         let cloned_index = index.clone_ref(py);
   201         let index = py_rust_index_to_graph(py, index)?;
   209         let index = py_rust_index_to_graph(py, index)?;
   202         let initvec: Vec<_> = {
   210         let initvec: Vec<_> = {
       
   211             // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   203             let borrowed_idx =  unsafe {index.try_borrow(py)?};
   212             let borrowed_idx =  unsafe {index.try_borrow(py)?};
   204             rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
   213             rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
   205         };
   214         };
   206 
   215 
       
   216         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   207         let res_lazy =
   217         let res_lazy =
   208             unsafe { index.map(py, |idx| VCGLazyAncestors::new(
   218             unsafe { index.map(py, |idx| VCGLazyAncestors::new(
   209                 idx,
   219                 idx,
   210                 initvec.into_iter().map(|r| r.0),
   220                 initvec.into_iter().map(|r| r.0),
   211                 stoprev.0,
   221                 stoprev.0,
   212                 inclusive
   222                 inclusive
   213             ))};
   223             ))};
   214         let lazy = pyleaked_or_map_err(py, res_lazy,
   224         let lazy = pyleaked_or_map_err(py, res_lazy,
   215                                        GraphError::pynew_from_vcsgraph)?;
   225                                        GraphError::pynew_from_vcsgraph)?;
       
   226         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   216         let lazy_cell = unsafe { lazy.map(py, RefCell::new)};
   227         let lazy_cell = unsafe { lazy.map(py, RefCell::new)};
   217         let res = Self::create_instance(
   228         let res = Self::create_instance(
   218             py, RefCell::new(lazy_cell),
   229             py, RefCell::new(lazy_cell),
   219             cloned_index, initrevs, stoprev, inclusive)?;
   230             cloned_index, initrevs, stoprev, inclusive)?;
   220         Ok(res)
   231         Ok(res)
   234         bases: PyObject
   245         bases: PyObject
   235     )
   246     )
   236     -> PyResult<MissingAncestors> {
   247     -> PyResult<MissingAncestors> {
   237         let cloned_index = index.clone_ref(py);
   248         let cloned_index = index.clone_ref(py);
   238         let inner_index = py_rust_index_to_graph(py, index)?;
   249         let inner_index = py_rust_index_to_graph(py, index)?;
       
   250         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   239         let bases_vec: Vec<_> = {
   251         let bases_vec: Vec<_> = {
   240             let borrowed_idx = unsafe { inner_index.try_borrow(py)? };
   252             let borrowed_idx = unsafe { inner_index.try_borrow(py)? };
   241             rev_pyiter_collect(py, &bases, &*borrowed_idx)?
   253             rev_pyiter_collect(py, &bases, &*borrowed_idx)?
   242         };
   254         };
   243 
   255 
       
   256         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   244         let inner = unsafe {
   257         let inner = unsafe {
   245             inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec))
   258             inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec))
   246         };
   259         };
   247         MissingAncestors::create_instance(
   260         MissingAncestors::create_instance(
   248             py,
   261             py,
   251         )
   264         )
   252     }
   265     }
   253 
   266 
   254     def hasbases(&self) -> PyResult<bool> {
   267     def hasbases(&self) -> PyResult<bool> {
   255         let leaked = self.inner(py).borrow();
   268         let leaked = self.inner(py).borrow();
       
   269         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   256         let inner: &CoreMissing<PySharedIndex> =
   270         let inner: &CoreMissing<PySharedIndex> =
   257             &*unsafe { leaked.try_borrow(py)? };
   271             &*unsafe { leaked.try_borrow(py)? };
   258         Ok(inner.has_bases())
   272         Ok(inner.has_bases())
   259     }
   273     }
   260 
   274 
   261     def addbases(&self, bases: PyObject) -> PyResult<PyObject> {
   275     def addbases(&self, bases: PyObject) -> PyResult<PyObject> {
   262         let bases_vec: Vec<_> = {
   276         let bases_vec: Vec<_> = {
   263             let leaked = py_rust_index_to_graph(py,
   277             let leaked = py_rust_index_to_graph(py,
   264                                                self.index(py).clone_ref(py))?;
   278                                                self.index(py).clone_ref(py))?;
       
   279             // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   265             let index = &*unsafe { leaked.try_borrow(py)? };
   280             let index = &*unsafe { leaked.try_borrow(py)? };
   266             rev_pyiter_collect(py, &bases, index)?
   281             rev_pyiter_collect(py, &bases, index)?
   267         };
   282         };
   268 
   283 
   269         let mut leaked = self.inner(py).borrow_mut();
   284         let mut leaked = self.inner(py).borrow_mut();
       
   285         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   270         let inner: &mut CoreMissing<PySharedIndex> =
   286         let inner: &mut CoreMissing<PySharedIndex> =
   271             &mut *unsafe { leaked.try_borrow_mut(py)? };
   287             &mut *unsafe { leaked.try_borrow_mut(py)? };
   272 
   288 
   273         inner.add_bases(bases_vec);
   289         inner.add_bases(bases_vec);
   274         // cpython doc has examples with PyResult<()> but this gives me
   290         // cpython doc has examples with PyResult<()> but this gives me
   277         Ok(py.None())
   293         Ok(py.None())
   278     }
   294     }
   279 
   295 
   280     def bases(&self) -> PyResult<HashSet<PyRevision>> {
   296     def bases(&self) -> PyResult<HashSet<PyRevision>> {
   281         let leaked = self.inner(py).borrow();
   297         let leaked = self.inner(py).borrow();
       
   298         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   282         let inner: &CoreMissing<PySharedIndex> =
   299         let inner: &CoreMissing<PySharedIndex> =
   283             &*unsafe { leaked.try_borrow(py)? };
   300             &*unsafe { leaked.try_borrow(py)? };
   284         Ok(inner.get_bases()
   301         Ok(inner.get_bases()
   285            .iter()
   302            .iter()
   286            .map(|r| PyRevision(r.0))
   303            .map(|r| PyRevision(r.0))
   288         )
   305         )
   289     }
   306     }
   290 
   307 
   291     def basesheads(&self) -> PyResult<HashSet<PyRevision>> {
   308     def basesheads(&self) -> PyResult<HashSet<PyRevision>> {
   292         let leaked = self.inner(py).borrow();
   309         let leaked = self.inner(py).borrow();
       
   310         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   293         let inner: &CoreMissing<PySharedIndex> =
   311         let inner: &CoreMissing<PySharedIndex> =
   294             &*unsafe { leaked.try_borrow(py)? };
   312             &*unsafe { leaked.try_borrow(py)? };
   295         Ok(
   313         Ok(
   296             inner
   314             inner
   297                 .bases_heads()
   315                 .bases_heads()
   313             //    discard
   331             //    discard
   314             //  - define a trait for sets of revisions in the core and
   332             //  - define a trait for sets of revisions in the core and
   315             //    implement it for a Python set rewrapped with the GIL marker
   333             //    implement it for a Python set rewrapped with the GIL marker
   316             let leaked = py_rust_index_to_graph(py,
   334             let leaked = py_rust_index_to_graph(py,
   317                                                self.index(py).clone_ref(py))?;
   335                                                self.index(py).clone_ref(py))?;
       
   336             // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   318             let index = &*unsafe { leaked.try_borrow(py)? };
   337             let index = &*unsafe { leaked.try_borrow(py)? };
   319             rev_pyiter_collect(py, &revs, &*index)?
   338             rev_pyiter_collect(py, &revs, &*index)?
   320         };
   339         };
   321 
   340 
   322         let mut leaked = self.inner(py).borrow_mut();
   341         let mut leaked = self.inner(py).borrow_mut();
       
   342         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   323         let inner: &mut CoreMissing<PySharedIndex> =
   343         let inner: &mut CoreMissing<PySharedIndex> =
   324             &mut *unsafe { leaked.try_borrow_mut(py)? };
   344             &mut *unsafe { leaked.try_borrow_mut(py)? };
   325 
   345 
   326         inner.remove_ancestors_from(&mut revs_pyset)
   346         inner.remove_ancestors_from(&mut revs_pyset)
   327             .map_err(|e| GraphError::pynew(py, e))?;
   347             .map_err(|e| GraphError::pynew(py, e))?;
   340 
   360 
   341     def missingancestors(&self, revs: PyObject) -> PyResult<PyList> {
   361     def missingancestors(&self, revs: PyObject) -> PyResult<PyList> {
   342         let revs_vec: Vec<Revision> = {
   362         let revs_vec: Vec<Revision> = {
   343             let leaked = py_rust_index_to_graph(py,
   363             let leaked = py_rust_index_to_graph(py,
   344                                                self.index(py).clone_ref(py))?;
   364                                                self.index(py).clone_ref(py))?;
       
   365             // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   345             let index = &*unsafe { leaked.try_borrow(py)? };
   366             let index = &*unsafe { leaked.try_borrow(py)? };
   346             rev_pyiter_collect(py, &revs, index)?
   367             rev_pyiter_collect(py, &revs, index)?
   347         };
   368         };
   348 
   369 
   349         let mut leaked = self.inner(py).borrow_mut();
   370         let mut leaked = self.inner(py).borrow_mut();
       
   371         // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
   350         let inner: &mut CoreMissing<PySharedIndex> =
   372         let inner: &mut CoreMissing<PySharedIndex> =
   351             &mut *unsafe { leaked.try_borrow_mut(py)? };
   373             &mut *unsafe { leaked.try_borrow_mut(py)? };
   352 
   374 
   353         let missing_vec = match inner.missing_ancestors(revs_vec) {
   375         let missing_vec = match inner.missing_ancestors(revs_vec) {
   354             Ok(missing) => missing,
   376             Ok(missing) => missing,