aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/pattern/usefulness.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern/usefulness.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/pattern/usefulness.rs81
1 files changed, 33 insertions, 48 deletions
diff --git a/crates/hir_ty/src/diagnostics/pattern/usefulness.rs b/crates/hir_ty/src/diagnostics/pattern/usefulness.rs
index 2df87ccea..28b9e71f8 100644
--- a/crates/hir_ty/src/diagnostics/pattern/usefulness.rs
+++ b/crates/hir_ty/src/diagnostics/pattern/usefulness.rs
@@ -3,11 +3,7 @@
3 3
4use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc}; 4use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc};
5 5
6use hir_def::{ 6use hir_def::{body::Body, expr::ExprId, HasModule, ModuleId};
7 body::Body,
8 expr::{ExprId, Pat, PatId},
9 HasModule, ModuleId,
10};
11use la_arena::Arena; 7use la_arena::Arena;
12use once_cell::unsync::OnceCell; 8use once_cell::unsync::OnceCell;
13use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
@@ -15,7 +11,10 @@ use smallvec::{smallvec, SmallVec};
15 11
16use crate::{db::HirDatabase, InferenceResult, Ty}; 12use crate::{db::HirDatabase, InferenceResult, Ty};
17 13
18use super::deconstruct_pat::{Constructor, Fields, SplitWildcard}; 14use super::{
15 deconstruct_pat::{Constructor, Fields, SplitWildcard},
16 Pat, PatId, PatKind,
17};
19 18
20use self::{ 19use self::{
21 helper::{Captures, PatIdExt}, 20 helper::{Captures, PatIdExt},
@@ -55,14 +54,13 @@ impl<'a> MatchCheckCtx<'a> {
55 false 54 false
56 } 55 }
57 56
58 pub(super) fn alloc_pat(&self, pat: Pat, ty: &Ty) -> PatId { 57 pub(super) fn alloc_pat(&self, pat: Pat) -> PatId {
59 self.pattern_arena.borrow_mut().alloc(pat, ty) 58 self.pattern_arena.borrow_mut().alloc(pat)
60 } 59 }
61 60
62 /// Get type of a pattern. Handles expanded patterns. 61 /// Get type of a pattern. Handles expanded patterns.
63 pub(super) fn type_of(&self, pat: PatId) -> Ty { 62 pub(super) fn type_of(&self, pat: PatId) -> Ty {
64 let type_of_expanded_pat = self.pattern_arena.borrow().type_of_epat.get(&pat).cloned(); 63 self.pattern_arena.borrow()[pat].ty.clone()
65 type_of_expanded_pat.unwrap_or_else(|| self.infer[pat].clone())
66 } 64 }
67} 65}
68 66
@@ -76,30 +74,40 @@ pub(super) struct PatCtxt<'a> {
76 pub(super) is_top_level: bool, 74 pub(super) is_top_level: bool,
77} 75}
78 76
79impl PatIdExt for PatId { 77pub(crate) fn expand_pattern(pat: Pat) -> Pat {
80 fn is_wildcard(self, cx: &MatchCheckCtx<'_>) -> bool { 78 // TODO: LiteralExpander, it is about string literal patterns
81 matches!(cx.pattern_arena.borrow()[self], Pat::Bind { subpat: None, .. } | Pat::Wild) 79 pat
80}
81
82impl Pat {
83 fn is_wildcard(&self) -> bool {
84 matches!(*self.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild)
82 } 85 }
86}
83 87
88impl PatIdExt for PatId {
84 fn is_or_pat(self, cx: &MatchCheckCtx<'_>) -> bool { 89 fn is_or_pat(self, cx: &MatchCheckCtx<'_>) -> bool {
85 matches!(cx.pattern_arena.borrow()[self], Pat::Or(..)) 90 matches!(*cx.pattern_arena.borrow()[self].kind, PatKind::Or { .. })
86 } 91 }
87 92
88 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. 93 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
89 fn expand_or_pat(self, cx: &MatchCheckCtx<'_>) -> Vec<Self> { 94 fn expand_or_pat(self, cx: &MatchCheckCtx<'_>) -> Vec<Self> {
90 fn expand(pat: PatId, vec: &mut Vec<PatId>, pat_arena: &PatternArena) { 95 fn expand(pat: PatId, vec: &mut Vec<PatId>, mut pat_arena: &mut PatternArena) {
91 if let Pat::Or(pats) = &pat_arena[pat] { 96 if let PatKind::Or { pats } = pat_arena[pat].kind.as_ref() {
92 for &pat in pats { 97 // for pat in pats {
93 expand(pat, vec, pat_arena); 98 // // TODO(iDawer): Ugh, I want to go back to references (PatId -> &Pat)
94 } 99 // let pat = pat_arena.alloc(pat.clone());
100 // expand(pat, vec, pat_arena);
101 // }
102 todo!()
95 } else { 103 } else {
96 vec.push(pat) 104 vec.push(pat)
97 } 105 }
98 } 106 }
99 107
100 let pat_arena = cx.pattern_arena.borrow(); 108 let mut pat_arena = cx.pattern_arena.borrow_mut();
101 let mut pats = Vec::new(); 109 let mut pats = Vec::new();
102 expand(self, &mut pats, &pat_arena); 110 expand(self, &mut pats, &mut pat_arena);
103 pats 111 pats
104 } 112 }
105} 113}
@@ -866,7 +874,8 @@ pub(crate) fn compute_match_usefulness(
866 }) 874 })
867 .collect(); 875 .collect();
868 876
869 let wild_pattern = cx.pattern_arena.borrow_mut().alloc(Pat::Wild, &cx.infer[cx.match_expr]); 877 let wild_pattern =
878 cx.pattern_arena.borrow_mut().alloc(Pat::wildcard_from_ty(&cx.infer[cx.match_expr]));
870 let v = PatStack::from_pattern(wild_pattern); 879 let v = PatStack::from_pattern(wild_pattern);
871 let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, false, true); 880 let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, false, true);
872 let non_exhaustiveness_witnesses = match usefulness { 881 let non_exhaustiveness_witnesses = match usefulness {
@@ -876,31 +885,7 @@ pub(crate) fn compute_match_usefulness(
876 UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses } 885 UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses }
877} 886}
878 887
879pub(crate) struct PatternArena { 888pub(crate) type PatternArena = Arena<Pat>;
880 arena: Arena<Pat>,
881 /// Types of expanded patterns.
882 type_of_epat: FxHashMap<PatId, Ty>,
883}
884
885impl PatternArena {
886 pub(crate) fn clone_from(pats: &Arena<Pat>) -> RefCell<Self> {
887 PatternArena { arena: pats.clone(), type_of_epat: Default::default() }.into()
888 }
889
890 fn alloc(&mut self, pat: Pat, ty: &Ty) -> PatId {
891 let id = self.arena.alloc(pat);
892 self.type_of_epat.insert(id, ty.clone());
893 id
894 }
895}
896
897impl Index<PatId> for PatternArena {
898 type Output = Pat;
899
900 fn index(&self, pat: PatId) -> &Pat {
901 &self.arena[pat]
902 }
903}
904 889
905mod helper { 890mod helper {
906 use hir_def::expr::{Pat, PatId}; 891 use hir_def::expr::{Pat, PatId};
@@ -908,7 +893,7 @@ mod helper {
908 use super::MatchCheckCtx; 893 use super::MatchCheckCtx;
909 894
910 pub(super) trait PatIdExt: Sized { 895 pub(super) trait PatIdExt: Sized {
911 fn is_wildcard(self, cx: &MatchCheckCtx<'_>) -> bool; 896 // fn is_wildcard(self, cx: &MatchCheckCtx<'_>) -> bool;
912 fn is_or_pat(self, cx: &MatchCheckCtx<'_>) -> bool; 897 fn is_or_pat(self, cx: &MatchCheckCtx<'_>) -> bool;
913 fn expand_or_pat(self, cx: &MatchCheckCtx<'_>) -> Vec<Self>; 898 fn expand_or_pat(self, cx: &MatchCheckCtx<'_>) -> Vec<Self>;
914 } 899 }