Show More
@@ -294,7 +294,13 b' impl<T> PyLeaked<T> {' | |||
|
294 | 294 | /// Immutably borrows the wrapped value. |
|
295 | 295 | /// |
|
296 | 296 | /// Borrowing fails if the underlying reference has been invalidated. |
|
297 | pub fn try_borrow<'a>( | |
|
297 | /// | |
|
298 | /// # Safety | |
|
299 | /// | |
|
300 | /// The lifetime of the innermost object is cheated. Do not obtain and | |
|
301 | /// copy it out of the borrow scope. See the example of `try_borrow_mut()` | |
|
302 | /// for details. | |
|
303 | pub unsafe fn try_borrow<'a>( | |
|
298 | 304 | &'a self, |
|
299 | 305 | py: Python<'a>, |
|
300 | 306 | ) -> PyResult<PyLeakedRef<'a, T>> { |
@@ -311,7 +317,24 b' impl<T> PyLeaked<T> {' | |||
|
311 | 317 | /// |
|
312 | 318 | /// Typically `T` is an iterator. If `T` is an immutable reference, |
|
313 | 319 | /// `get_mut()` is useless since the inner value can't be mutated. |
|
314 | pub fn try_borrow_mut<'a>( | |
|
320 | /// | |
|
321 | /// # Safety | |
|
322 | /// | |
|
323 | /// The lifetime of the innermost object is cheated. Do not obtain and | |
|
324 | /// copy it out of the borrow scope. For example, the following code | |
|
325 | /// is unsafe: | |
|
326 | /// | |
|
327 | /// ```compile_fail | |
|
328 | /// let slice; | |
|
329 | /// { | |
|
330 | /// let iter = leaked.try_borrow_mut(py); | |
|
331 | /// // slice can outlive since the iterator is of Iter<'static, T> | |
|
332 | /// // type, but it shouldn't. | |
|
333 | /// slice = iter.as_slice(); | |
|
334 | /// } | |
|
335 | /// println!("{:?}", slice); | |
|
336 | /// ``` | |
|
337 | pub unsafe fn try_borrow_mut<'a>( | |
|
315 | 338 | &'a mut self, |
|
316 | 339 | py: Python<'a>, |
|
317 | 340 | ) -> PyResult<PyLeakedRefMut<'a, T>> { |
@@ -423,6 +446,11 b" impl<T> DerefMut for PyLeakedRefMut<'_, " | |||
|
423 | 446 | /// tuple on iteration success, turning it into something Python understands. |
|
424 | 447 | /// * `$success_func` is the return type of `$success_func` |
|
425 | 448 | /// |
|
449 | /// # Safety | |
|
450 | /// | |
|
451 | /// `$success_func` may take a reference, but it's lifetime may be cheated. | |
|
452 | /// Do not copy it out of the function call. | |
|
453 | /// | |
|
426 | 454 | /// # Example |
|
427 | 455 | /// |
|
428 | 456 | /// ``` |
@@ -476,9 +504,10 b' macro_rules! py_shared_iterator {' | |||
|
476 | 504 | |
|
477 | 505 | def __next__(&self) -> PyResult<$success_type> { |
|
478 | 506 | let mut leaked = self.inner(py).borrow_mut(); |
|
479 | let mut iter = leaked.try_borrow_mut(py)?; | |
|
507 | let mut iter = unsafe { leaked.try_borrow_mut(py)? }; | |
|
480 | 508 | match iter.next() { |
|
481 | 509 | None => Ok(None), |
|
510 | // res may be a reference of cheated 'static lifetime | |
|
482 | 511 | Some(res) => $success_func(py, res), |
|
483 | 512 | } |
|
484 | 513 | } |
@@ -527,7 +556,7 b' mod test {' | |||
|
527 | 556 | let (gil, owner) = prepare_env(); |
|
528 | 557 | let py = gil.python(); |
|
529 | 558 | let leaked = owner.string_shared(py).leak_immutable(); |
|
530 | let leaked_ref = leaked.try_borrow(py).unwrap(); | |
|
559 | let leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); | |
|
531 | 560 | assert_eq!(*leaked_ref, "new"); |
|
532 | 561 | } |
|
533 | 562 | |
@@ -537,7 +566,8 b' mod test {' | |||
|
537 | 566 | let py = gil.python(); |
|
538 | 567 | let leaked = owner.string_shared(py).leak_immutable(); |
|
539 | 568 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
540 | let mut leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); | |
|
569 | let mut leaked_ref = | |
|
570 | unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); | |
|
541 | 571 | assert_eq!(leaked_ref.next(), Some('n')); |
|
542 | 572 | assert_eq!(leaked_ref.next(), Some('e')); |
|
543 | 573 | assert_eq!(leaked_ref.next(), Some('w')); |
@@ -550,7 +580,7 b' mod test {' | |||
|
550 | 580 | let py = gil.python(); |
|
551 | 581 | let leaked = owner.string_shared(py).leak_immutable(); |
|
552 | 582 | owner.string_shared(py).borrow_mut().clear(); |
|
553 | assert!(leaked.try_borrow(py).is_err()); | |
|
583 | assert!(unsafe { leaked.try_borrow(py) }.is_err()); | |
|
554 | 584 | } |
|
555 | 585 | |
|
556 | 586 | #[test] |
@@ -560,7 +590,7 b' mod test {' | |||
|
560 | 590 | let leaked = owner.string_shared(py).leak_immutable(); |
|
561 | 591 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
562 | 592 | owner.string_shared(py).borrow_mut().clear(); |
|
563 | assert!(leaked_iter.try_borrow_mut(py).is_err()); | |
|
593 | assert!(unsafe { leaked_iter.try_borrow_mut(py) }.is_err()); | |
|
564 | 594 | } |
|
565 | 595 | |
|
566 | 596 | #[test] |
@@ -580,10 +610,10 b' mod test {' | |||
|
580 | 610 | assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
|
581 | 611 | let leaked = owner.string_shared(py).leak_immutable(); |
|
582 | 612 | { |
|
583 | let _leaked_ref = leaked.try_borrow(py).unwrap(); | |
|
613 | let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap(); | |
|
584 | 614 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
585 | 615 | { |
|
586 | let _leaked_ref2 = leaked.try_borrow(py).unwrap(); | |
|
616 | let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap(); | |
|
587 | 617 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
588 | 618 | } |
|
589 | 619 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
@@ -599,7 +629,8 b' mod test {' | |||
|
599 | 629 | let leaked = owner.string_shared(py).leak_immutable(); |
|
600 | 630 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
601 | 631 | { |
|
602 | let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); | |
|
632 | let _leaked_ref = | |
|
633 | unsafe { leaked_iter.try_borrow_mut(py) }.unwrap(); | |
|
603 | 634 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
604 | 635 | } |
|
605 | 636 | assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
General Comments 0
You need to be logged in to leave comments.
Login now