Show More
@@ -294,7 +294,13 b' impl<T> PyLeaked<T> {' | |||||
294 | /// Immutably borrows the wrapped value. |
|
294 | /// Immutably borrows the wrapped value. | |
295 | /// |
|
295 | /// | |
296 | /// Borrowing fails if the underlying reference has been invalidated. |
|
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 | &'a self, |
|
304 | &'a self, | |
299 | py: Python<'a>, |
|
305 | py: Python<'a>, | |
300 | ) -> PyResult<PyLeakedRef<'a, T>> { |
|
306 | ) -> PyResult<PyLeakedRef<'a, T>> { | |
@@ -311,7 +317,24 b' impl<T> PyLeaked<T> {' | |||||
311 | /// |
|
317 | /// | |
312 | /// Typically `T` is an iterator. If `T` is an immutable reference, |
|
318 | /// Typically `T` is an iterator. If `T` is an immutable reference, | |
313 | /// `get_mut()` is useless since the inner value can't be mutated. |
|
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 | &'a mut self, |
|
338 | &'a mut self, | |
316 | py: Python<'a>, |
|
339 | py: Python<'a>, | |
317 | ) -> PyResult<PyLeakedRefMut<'a, T>> { |
|
340 | ) -> PyResult<PyLeakedRefMut<'a, T>> { | |
@@ -423,6 +446,11 b" impl<T> DerefMut for PyLeakedRefMut<'_, " | |||||
423 | /// tuple on iteration success, turning it into something Python understands. |
|
446 | /// tuple on iteration success, turning it into something Python understands. | |
424 | /// * `$success_func` is the return type of `$success_func` |
|
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 | /// # Example |
|
454 | /// # Example | |
427 | /// |
|
455 | /// | |
428 | /// ``` |
|
456 | /// ``` | |
@@ -476,9 +504,10 b' macro_rules! py_shared_iterator {' | |||||
476 |
|
504 | |||
477 | def __next__(&self) -> PyResult<$success_type> { |
|
505 | def __next__(&self) -> PyResult<$success_type> { | |
478 | let mut leaked = self.inner(py).borrow_mut(); |
|
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 | match iter.next() { |
|
508 | match iter.next() { | |
481 | None => Ok(None), |
|
509 | None => Ok(None), | |
|
510 | // res may be a reference of cheated 'static lifetime | |||
482 | Some(res) => $success_func(py, res), |
|
511 | Some(res) => $success_func(py, res), | |
483 | } |
|
512 | } | |
484 | } |
|
513 | } | |
@@ -527,7 +556,7 b' mod test {' | |||||
527 | let (gil, owner) = prepare_env(); |
|
556 | let (gil, owner) = prepare_env(); | |
528 | let py = gil.python(); |
|
557 | let py = gil.python(); | |
529 | let leaked = owner.string_shared(py).leak_immutable(); |
|
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 | assert_eq!(*leaked_ref, "new"); |
|
560 | assert_eq!(*leaked_ref, "new"); | |
532 | } |
|
561 | } | |
533 |
|
562 | |||
@@ -537,7 +566,8 b' mod test {' | |||||
537 | let py = gil.python(); |
|
566 | let py = gil.python(); | |
538 | let leaked = owner.string_shared(py).leak_immutable(); |
|
567 | let leaked = owner.string_shared(py).leak_immutable(); | |
539 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
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 | assert_eq!(leaked_ref.next(), Some('n')); |
|
571 | assert_eq!(leaked_ref.next(), Some('n')); | |
542 | assert_eq!(leaked_ref.next(), Some('e')); |
|
572 | assert_eq!(leaked_ref.next(), Some('e')); | |
543 | assert_eq!(leaked_ref.next(), Some('w')); |
|
573 | assert_eq!(leaked_ref.next(), Some('w')); | |
@@ -550,7 +580,7 b' mod test {' | |||||
550 | let py = gil.python(); |
|
580 | let py = gil.python(); | |
551 | let leaked = owner.string_shared(py).leak_immutable(); |
|
581 | let leaked = owner.string_shared(py).leak_immutable(); | |
552 | owner.string_shared(py).borrow_mut().clear(); |
|
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 | #[test] |
|
586 | #[test] | |
@@ -560,7 +590,7 b' mod test {' | |||||
560 | let leaked = owner.string_shared(py).leak_immutable(); |
|
590 | let leaked = owner.string_shared(py).leak_immutable(); | |
561 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
591 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | |
562 | owner.string_shared(py).borrow_mut().clear(); |
|
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 | #[test] |
|
596 | #[test] | |
@@ -580,10 +610,10 b' mod test {' | |||||
580 | assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
|
610 | assert!(owner.string_shared(py).try_borrow_mut().is_ok()); | |
581 | let leaked = owner.string_shared(py).leak_immutable(); |
|
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 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
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 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
617 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); | |
588 | } |
|
618 | } | |
589 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
619 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); | |
@@ -599,7 +629,8 b' mod test {' | |||||
599 | let leaked = owner.string_shared(py).leak_immutable(); |
|
629 | let leaked = owner.string_shared(py).leak_immutable(); | |
600 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
|
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 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
|
634 | assert!(owner.string_shared(py).try_borrow_mut().is_err()); | |
604 | } |
|
635 | } | |
605 | assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
|
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