Check deadlock possibility. for two lockguards, first check if their types may deadlock; if so, then check if they may alias.
(
a: &LockGuardId,
b: &LockGuardId,
lockguards: &LockGuardMap<'_>,
alias_analysis: &mut AliasAnalysis,
)
| 674 | "ConflictLock".to_owned(), |
| 675 | "Possibly".to_owned(), |
| 676 | diagnosis, |
| 677 | "Locks mutually wait for each other to form a cycle".to_owned(), |
| 678 | )); |
| 679 | reports.push(report); |
| 680 | } |
| 681 | reports |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 686 | enum NotDeadlockReason { |
| 687 | TrueDeadlock, |
| 688 | RecursiveRead, |
| 689 | SameSpan, |
| 690 | // TODO, |
| 691 | } |
| 692 | |
| 693 | /// Check deadlock possibility. |
| 694 | /// for two lockguards, first check if their types may deadlock; |
| 695 | /// if so, then check if they may alias. |
| 696 | fn deadlock_possibility( |
| 697 | a: &LockGuardId, |
| 698 | b: &LockGuardId, |
| 699 | lockguards: &LockGuardMap<'_>, |
| 700 | alias_analysis: &mut AliasAnalysis, |
| 701 | ) -> (DeadlockPossibility, NotDeadlockReason) { |
| 702 | let a_ty = &lockguards[a].lockguard_ty; |
| 703 | let b_ty = &lockguards[b].lockguard_ty; |
| 704 | if let (LockGuardTy::ParkingLotRead(_), LockGuardTy::ParkingLotRead(_)) = (a_ty, b_ty) { |
| 705 | if lockguards[b].is_gen_only_by_recursive() { |
| 706 | return ( |
| 707 | DeadlockPossibility::Unlikely, |
| 708 | NotDeadlockReason::RecursiveRead, |
| 709 | ); |
| 710 | } |
| 711 | } |
| 712 | // Assume that a lock in a loop or recursive functions will not deadlock with itself, |
| 713 | // in which case the lock spans of the two locks are the same. |
| 714 | // This may miss some bugs but can reduce many FPs. |
| 715 | if lockguards[a].span == lockguards[b].span { |
| 716 | return (DeadlockPossibility::Unlikely, NotDeadlockReason::SameSpan); |
| 717 | } |
no test coverage detected