Mercurial > public > mercurial-scm > hg
comparison rust/hg-cpython/src/ref_sharing.rs @ 44203:2a24ead003f0
rust-cpython: add panicking version of borrow_mut() and use it
The original borrow_mut() is renamed to try_borrow_mut().
Since leak_immutable() no longer incref the borrow count, the caller should
know if the underlying value is borrowed or not. No Python world is involved.
That's why we can simply use the panicking borrow_mut().
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 12 Oct 2019 23:34:05 +0900 |
parents | 4a4c3b9fd91b |
children | bafdaf4858d8 |
comparison
equal
deleted
inserted
replaced
44202:a7f8160cc4e4 | 44203:2a24ead003f0 |
---|---|
200 | 200 |
201 pub fn borrow(&self) -> Ref<'a, T> { | 201 pub fn borrow(&self) -> Ref<'a, T> { |
202 self.data.borrow(self.py) | 202 self.data.borrow(self.py) |
203 } | 203 } |
204 | 204 |
205 pub fn borrow_mut(&self) -> PyResult<RefMut<'a, T>> { | 205 /// Mutably borrows the wrapped value. |
206 /// | |
207 /// # Panics | |
208 /// | |
209 /// Panics if the value is currently borrowed through `PySharedRef` | |
210 /// or `PyLeaked`. | |
211 pub fn borrow_mut(&self) -> RefMut<'a, T> { | |
212 self.try_borrow_mut().expect("already borrowed") | |
213 } | |
214 | |
215 /// Mutably borrows the wrapped value, returning an error if the value | |
216 /// is currently borrowed. | |
217 pub fn try_borrow_mut(&self) -> PyResult<RefMut<'a, T>> { | |
206 self.data.try_borrow_mut(self.py) | 218 self.data.try_borrow_mut(self.py) |
207 } | 219 } |
208 | 220 |
209 /// Returns a leaked reference. | 221 /// Returns a leaked reference. |
210 /// | 222 /// |
570 #[test] | 582 #[test] |
571 fn test_leaked_borrow_after_mut() { | 583 fn test_leaked_borrow_after_mut() { |
572 let (gil, owner) = prepare_env(); | 584 let (gil, owner) = prepare_env(); |
573 let py = gil.python(); | 585 let py = gil.python(); |
574 let leaked = owner.string_shared(py).leak_immutable(); | 586 let leaked = owner.string_shared(py).leak_immutable(); |
575 owner.string_shared(py).borrow_mut().unwrap().clear(); | 587 owner.string_shared(py).borrow_mut().clear(); |
576 assert!(leaked.try_borrow(py).is_err()); | 588 assert!(leaked.try_borrow(py).is_err()); |
577 } | 589 } |
578 | 590 |
579 #[test] | 591 #[test] |
580 fn test_leaked_borrow_mut_after_mut() { | 592 fn test_leaked_borrow_mut_after_mut() { |
581 let (gil, owner) = prepare_env(); | 593 let (gil, owner) = prepare_env(); |
582 let py = gil.python(); | 594 let py = gil.python(); |
583 let leaked = owner.string_shared(py).leak_immutable(); | 595 let leaked = owner.string_shared(py).leak_immutable(); |
584 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | 596 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
585 owner.string_shared(py).borrow_mut().unwrap().clear(); | 597 owner.string_shared(py).borrow_mut().clear(); |
586 assert!(leaked_iter.try_borrow_mut(py).is_err()); | 598 assert!(leaked_iter.try_borrow_mut(py).is_err()); |
587 } | 599 } |
588 | 600 |
589 #[test] | 601 #[test] |
590 #[should_panic(expected = "map() over invalidated leaked reference")] | 602 #[should_panic(expected = "map() over invalidated leaked reference")] |
591 fn test_leaked_map_after_mut() { | 603 fn test_leaked_map_after_mut() { |
592 let (gil, owner) = prepare_env(); | 604 let (gil, owner) = prepare_env(); |
593 let py = gil.python(); | 605 let py = gil.python(); |
594 let leaked = owner.string_shared(py).leak_immutable(); | 606 let leaked = owner.string_shared(py).leak_immutable(); |
595 owner.string_shared(py).borrow_mut().unwrap().clear(); | 607 owner.string_shared(py).borrow_mut().clear(); |
596 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | 608 let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
597 } | 609 } |
598 | 610 |
599 #[test] | 611 #[test] |
600 fn test_borrow_mut_while_leaked_ref() { | 612 fn test_try_borrow_mut_while_leaked_ref() { |
601 let (gil, owner) = prepare_env(); | 613 let (gil, owner) = prepare_env(); |
602 let py = gil.python(); | 614 let py = gil.python(); |
603 assert!(owner.string_shared(py).borrow_mut().is_ok()); | 615 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
604 let leaked = owner.string_shared(py).leak_immutable(); | 616 let leaked = owner.string_shared(py).leak_immutable(); |
605 { | 617 { |
606 let _leaked_ref = leaked.try_borrow(py).unwrap(); | 618 let _leaked_ref = leaked.try_borrow(py).unwrap(); |
607 assert!(owner.string_shared(py).borrow_mut().is_err()); | 619 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
608 { | 620 { |
609 let _leaked_ref2 = leaked.try_borrow(py).unwrap(); | 621 let _leaked_ref2 = leaked.try_borrow(py).unwrap(); |
610 assert!(owner.string_shared(py).borrow_mut().is_err()); | 622 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
611 } | 623 } |
612 assert!(owner.string_shared(py).borrow_mut().is_err()); | 624 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
613 } | 625 } |
614 assert!(owner.string_shared(py).borrow_mut().is_ok()); | 626 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
615 } | 627 } |
616 | 628 |
617 #[test] | 629 #[test] |
618 fn test_borrow_mut_while_leaked_ref_mut() { | 630 fn test_try_borrow_mut_while_leaked_ref_mut() { |
619 let (gil, owner) = prepare_env(); | 631 let (gil, owner) = prepare_env(); |
620 let py = gil.python(); | 632 let py = gil.python(); |
621 assert!(owner.string_shared(py).borrow_mut().is_ok()); | 633 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
622 let leaked = owner.string_shared(py).leak_immutable(); | 634 let leaked = owner.string_shared(py).leak_immutable(); |
623 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | 635 let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; |
624 { | 636 { |
625 let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); | 637 let _leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); |
626 assert!(owner.string_shared(py).borrow_mut().is_err()); | 638 assert!(owner.string_shared(py).try_borrow_mut().is_err()); |
627 } | 639 } |
628 assert!(owner.string_shared(py).borrow_mut().is_ok()); | 640 assert!(owner.string_shared(py).try_borrow_mut().is_ok()); |
629 } | 641 } |
630 | 642 |
631 #[test] | 643 #[test] |
632 #[should_panic(expected = "mutably borrowed")] | 644 #[should_panic(expected = "mutably borrowed")] |
633 fn test_leak_while_borrow_mut() { | 645 fn test_leak_while_borrow_mut() { |
636 let _mut_ref = owner.string_shared(py).borrow_mut(); | 648 let _mut_ref = owner.string_shared(py).borrow_mut(); |
637 owner.string_shared(py).leak_immutable(); | 649 owner.string_shared(py).leak_immutable(); |
638 } | 650 } |
639 | 651 |
640 #[test] | 652 #[test] |
653 fn test_try_borrow_mut_while_borrow() { | |
654 let (gil, owner) = prepare_env(); | |
655 let py = gil.python(); | |
656 let _ref = owner.string_shared(py).borrow(); | |
657 assert!(owner.string_shared(py).try_borrow_mut().is_err()); | |
658 } | |
659 | |
660 #[test] | |
661 #[should_panic(expected = "already borrowed")] | |
641 fn test_borrow_mut_while_borrow() { | 662 fn test_borrow_mut_while_borrow() { |
642 let (gil, owner) = prepare_env(); | 663 let (gil, owner) = prepare_env(); |
643 let py = gil.python(); | 664 let py = gil.python(); |
644 let _ref = owner.string_shared(py).borrow(); | 665 let _ref = owner.string_shared(py).borrow(); |
645 assert!(owner.string_shared(py).borrow_mut().is_err()); | 666 owner.string_shared(py).borrow_mut(); |
646 } | 667 } |
647 } | 668 } |