diff options
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern/usefulness.rs')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/usefulness.rs | 81 |
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 | ||
4 | use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc}; | 4 | use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc}; |
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{body::Body, expr::ExprId, HasModule, ModuleId}; |
7 | body::Body, | ||
8 | expr::{ExprId, Pat, PatId}, | ||
9 | HasModule, ModuleId, | ||
10 | }; | ||
11 | use la_arena::Arena; | 7 | use la_arena::Arena; |
12 | use once_cell::unsync::OnceCell; | 8 | use once_cell::unsync::OnceCell; |
13 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
@@ -15,7 +11,10 @@ use smallvec::{smallvec, SmallVec}; | |||
15 | 11 | ||
16 | use crate::{db::HirDatabase, InferenceResult, Ty}; | 12 | use crate::{db::HirDatabase, InferenceResult, Ty}; |
17 | 13 | ||
18 | use super::deconstruct_pat::{Constructor, Fields, SplitWildcard}; | 14 | use super::{ |
15 | deconstruct_pat::{Constructor, Fields, SplitWildcard}, | ||
16 | Pat, PatId, PatKind, | ||
17 | }; | ||
19 | 18 | ||
20 | use self::{ | 19 | use 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 | ||
79 | impl PatIdExt for PatId { | 77 | pub(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 | |||
82 | impl Pat { | ||
83 | fn is_wildcard(&self) -> bool { | ||
84 | matches!(*self.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild) | ||
82 | } | 85 | } |
86 | } | ||
83 | 87 | ||
88 | impl 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 | ||
879 | pub(crate) struct PatternArena { | 888 | pub(crate) type PatternArena = Arena<Pat>; |
880 | arena: Arena<Pat>, | ||
881 | /// Types of expanded patterns. | ||
882 | type_of_epat: FxHashMap<PatId, Ty>, | ||
883 | } | ||
884 | |||
885 | impl 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 | |||
897 | impl Index<PatId> for PatternArena { | ||
898 | type Output = Pat; | ||
899 | |||
900 | fn index(&self, pat: PatId) -> &Pat { | ||
901 | &self.arena[pat] | ||
902 | } | ||
903 | } | ||
904 | 889 | ||
905 | mod helper { | 890 | mod 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 | } |