diff options
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs | 188 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/pat_util.rs | 52 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/usefulness.rs | 81 |
3 files changed, 166 insertions, 155 deletions
diff --git a/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs index 248a379b3..479e0dc73 100644 --- a/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs +++ b/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs | |||
@@ -5,18 +5,18 @@ use std::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Expr, Literal, Pat, PatId, RecordFieldPat}, | 8 | expr::{Expr, Literal, RecordFieldPat}, |
9 | find_path::find_path, | ||
10 | item_scope::ItemInNs, | ||
11 | path::Path, | ||
12 | type_ref::Mutability, | 9 | type_ref::Mutability, |
13 | AttrDefId, EnumVariantId, HasModule, VariantId, | 10 | AttrDefId, EnumVariantId, HasModule, LocalFieldId, VariantId, |
14 | }; | 11 | }; |
15 | use smallvec::{smallvec, SmallVec}; | 12 | use smallvec::{smallvec, SmallVec}; |
16 | 13 | ||
17 | use crate::{AdtId, Interner, Scalar, Ty, TyExt, TyKind}; | 14 | use crate::{AdtId, Interner, Scalar, Ty, TyExt, TyKind}; |
18 | 15 | ||
19 | use super::usefulness::{MatchCheckCtx, PatCtxt}; | 16 | use super::{ |
17 | usefulness::{MatchCheckCtx, PatCtxt}, | ||
18 | FieldPat, Pat, PatId, PatKind, | ||
19 | }; | ||
20 | 20 | ||
21 | use self::Constructor::*; | 21 | use self::Constructor::*; |
22 | 22 | ||
@@ -271,29 +271,18 @@ impl Constructor { | |||
271 | /// Determines the constructor that the given pattern can be specialized to. | 271 | /// Determines the constructor that the given pattern can be specialized to. |
272 | pub(super) fn from_pat(cx: &MatchCheckCtx<'_>, pat: PatId) -> Self { | 272 | pub(super) fn from_pat(cx: &MatchCheckCtx<'_>, pat: PatId) -> Self { |
273 | let ty = cx.type_of(pat); | 273 | let ty = cx.type_of(pat); |
274 | match &cx.pattern_arena.borrow()[pat] { | 274 | match cx.pattern_arena.borrow()[pat].kind.as_ref() { |
275 | Pat::Bind { .. } | Pat::Wild => Wildcard, | 275 | PatKind::Binding { .. } | PatKind::Wild => Wildcard, |
276 | Pat::Tuple { .. } | Pat::Ref { .. } | Pat::Box { .. } => Single, | 276 | PatKind::Leaf { .. } | PatKind::Deref { .. } => Single, |
277 | Pat::Record { .. } | Pat::Path(_) | Pat::TupleStruct { .. } => { | 277 | &PatKind::Variant { enum_variant, .. } => Variant(enum_variant), |
278 | // TODO: path to const | 278 | |
279 | let variant_id = | 279 | //Todo |
280 | cx.infer.variant_resolution_for_pat(pat).unwrap_or_else(|| todo!()); | 280 | // &Pat::Lit(expr_id) => match cx.body[expr_id] { |
281 | match variant_id { | 281 | // Expr::Literal(Literal::Bool(val)) => IntRange(IntRange::from_bool(val)), |
282 | VariantId::EnumVariantId(id) => Variant(id), | 282 | // _ => todo!(), |
283 | VariantId::StructId(_) | VariantId::UnionId(_) => Single, | 283 | // }, |
284 | } | 284 | PatKind::Or { .. } => panic!("bug: Or-pattern should have been expanded earlier on."), |
285 | } | ||
286 | &Pat::Lit(expr_id) => match cx.body[expr_id] { | ||
287 | Expr::Literal(Literal::Bool(val)) => IntRange(IntRange::from_bool(val)), | ||
288 | _ => todo!(), | ||
289 | }, | ||
290 | |||
291 | Pat::Or(..) => panic!("bug: Or-pattern should have been expanded earlier on."), | ||
292 | Pat::Missing => todo!("Fail gracefully when there is an error in a pattern"), | ||
293 | pat => todo!("Constructor::from_pat {:?}", pat), | 285 | pat => todo!("Constructor::from_pat {:?}", pat), |
294 | // Pat::Range { start, end } => {} | ||
295 | // Pat::Slice { prefix, slice, suffix } => {} | ||
296 | // Pat::ConstBlock(_) => {} | ||
297 | } | 286 | } |
298 | } | 287 | } |
299 | 288 | ||
@@ -620,15 +609,15 @@ impl Fields { | |||
620 | cx: &MatchCheckCtx<'_>, | 609 | cx: &MatchCheckCtx<'_>, |
621 | tys: impl IntoIterator<Item = &'a Ty>, | 610 | tys: impl IntoIterator<Item = &'a Ty>, |
622 | ) -> Self { | 611 | ) -> Self { |
623 | let wilds = tys.into_iter().map(|ty| (Pat::Wild, ty)); | 612 | let wilds = tys.into_iter().map(Pat::wildcard_from_ty); |
624 | let pats = wilds.map(|(pat, ty)| cx.alloc_pat(pat, ty)).collect(); | 613 | let pats = wilds.map(|pat| cx.alloc_pat(pat)).collect(); |
625 | Fields::Vec(pats) | 614 | Fields::Vec(pats) |
626 | } | 615 | } |
627 | 616 | ||
628 | pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self { | 617 | pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self { |
629 | let ty = pcx.ty; | 618 | let ty = pcx.ty; |
630 | let cx = pcx.cx; | 619 | let cx = pcx.cx; |
631 | let wildcard_from_ty = |ty| cx.alloc_pat(Pat::Wild, ty); | 620 | let wildcard_from_ty = |ty| cx.alloc_pat(Pat::wildcard_from_ty(ty)); |
632 | 621 | ||
633 | let ret = match constructor { | 622 | let ret = match constructor { |
634 | Single | Variant(_) => match ty.kind(&Interner) { | 623 | Single | Variant(_) => match ty.kind(&Interner) { |
@@ -696,64 +685,60 @@ impl Fields { | |||
696 | /// returns `Some(false)` | 685 | /// returns `Some(false)` |
697 | pub(super) fn apply(self, pcx: PatCtxt<'_>, ctor: &Constructor) -> Pat { | 686 | pub(super) fn apply(self, pcx: PatCtxt<'_>, ctor: &Constructor) -> Pat { |
698 | let subpatterns_and_indices = self.patterns_and_indices(); | 687 | let subpatterns_and_indices = self.patterns_and_indices(); |
699 | let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p); | 688 | let mut subpatterns = |
700 | // TODO witnesses are not yet used | 689 | subpatterns_and_indices.iter().map(|&(_, p)| pcx.cx.pattern_arena.borrow()[p].clone()); |
701 | const TODO: Pat = Pat::Wild; | 690 | // FIXME(iDawer) witnesses are not yet used |
691 | const UNIMPLEMENTED: PatKind = PatKind::Wild; | ||
702 | 692 | ||
703 | match ctor { | 693 | let pat = match ctor { |
704 | Single | Variant(_) => match pcx.ty.kind(&Interner) { | 694 | Single | Variant(_) => match pcx.ty.kind(&Interner) { |
705 | TyKind::Adt(..) | TyKind::Tuple(..) => { | 695 | TyKind::Adt(..) | TyKind::Tuple(..) => { |
706 | // We want the real indices here. | 696 | // We want the real indices here. |
707 | // TODO indices and ellipsis interaction, tests | 697 | let subpatterns = subpatterns_and_indices |
708 | let subpatterns = subpatterns_and_indices.iter().map(|&(_, pat)| pat).collect(); | 698 | .iter() |
699 | .map(|&(field, pat)| FieldPat { | ||
700 | field, | ||
701 | pattern: pcx.cx.pattern_arena.borrow()[pat].clone(), | ||
702 | }) | ||
703 | .collect(); | ||
709 | 704 | ||
710 | if let Some((adt, substs)) = pcx.ty.as_adt() { | 705 | if let Some((adt, substs)) = pcx.ty.as_adt() { |
711 | let item = ItemInNs::Types(adt.into()); | 706 | if let hir_def::AdtId::EnumId(_) = adt { |
712 | let path = find_path(pcx.cx.db.upcast(), item, pcx.cx.module) | 707 | let enum_variant = match ctor { |
713 | .map(|mpath| Path::from_known_path(mpath, Vec::new()).into()); | 708 | &Variant(id) => id, |
714 | match adt { | 709 | _ => unreachable!(), |
715 | hir_def::AdtId::EnumId(id) => TODO, | 710 | }; |
716 | hir_def::AdtId::StructId(id) => { | 711 | PatKind::Variant { substs: substs.clone(), enum_variant, subpatterns } |
717 | let variant_data = &pcx.cx.db.struct_data(id).variant_data; | 712 | } else { |
718 | let args = subpatterns_and_indices | 713 | PatKind::Leaf { subpatterns } |
719 | .iter() | ||
720 | .zip(variant_data.fields().iter()) | ||
721 | .map(|(&(_, pat), (_, field_data))| RecordFieldPat { | ||
722 | name: field_data.name.clone(), | ||
723 | pat, | ||
724 | }) | ||
725 | .collect(); | ||
726 | Pat::Record { path, args, ellipsis: false } | ||
727 | } | ||
728 | hir_def::AdtId::UnionId(_) => Pat::Wild, | ||
729 | } | 714 | } |
730 | } else { | 715 | } else { |
731 | Pat::Tuple { args: subpatterns, ellipsis: None } | 716 | PatKind::Leaf { subpatterns } |
732 | } | 717 | } |
733 | } | 718 | } |
734 | // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should | 719 | // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should |
735 | // be careful to reconstruct the correct constant pattern here. However a string | 720 | // be careful to reconstruct the correct constant pattern here. However a string |
736 | // literal pattern will never be reported as a non-exhaustiveness witness, so we | 721 | // literal pattern will never be reported as a non-exhaustiveness witness, so we |
737 | // can ignore this issue. | 722 | // can ignore this issue. |
738 | TyKind::Ref(..) => { | 723 | TyKind::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, |
739 | Pat::Ref { pat: subpatterns.next().unwrap(), mutability: Mutability::Shared } | ||
740 | } | ||
741 | TyKind::Slice(..) | TyKind::Array(..) => { | 724 | TyKind::Slice(..) | TyKind::Array(..) => { |
742 | panic!("bug: bad slice pattern {:?} {:?}", ctor, pcx.ty) | 725 | panic!("bug: bad slice pattern {:?} {:?}", ctor, pcx.ty) |
743 | } | 726 | } |
744 | _ => Pat::Wild, | 727 | _ => PatKind::Wild, |
745 | }, | 728 | }, |
746 | Constructor::Slice(slice) => TODO, | 729 | Constructor::Slice(slice) => UNIMPLEMENTED, |
747 | Str(_) => TODO, | 730 | Str(_) => UNIMPLEMENTED, |
748 | FloatRange(..) => TODO, | 731 | FloatRange(..) => UNIMPLEMENTED, |
749 | Constructor::IntRange(_) => TODO, | 732 | Constructor::IntRange(_) => UNIMPLEMENTED, |
750 | NonExhaustive => Pat::Wild, | 733 | NonExhaustive => PatKind::Wild, |
751 | Wildcard => Pat::Wild, | 734 | Wildcard => return Pat::wildcard_from_ty(pcx.ty), |
752 | Opaque => panic!("bug: we should not try to apply an opaque constructor"), | 735 | Opaque => panic!("bug: we should not try to apply an opaque constructor"), |
753 | Missing => { | 736 | Missing => { |
754 | panic!("bug: trying to apply the `Missing` constructor; this should have been done in `apply_constructors`") | 737 | panic!("bug: trying to apply the `Missing` constructor; this should have been done in `apply_constructors`") |
755 | } | 738 | } |
756 | } | 739 | }; |
740 | |||
741 | Pat { ty: pcx.ty.clone(), kind: Box::new(pat) } | ||
757 | } | 742 | } |
758 | 743 | ||
759 | /// Returns the number of patterns. This is the same as the arity of the constructor used to | 744 | /// Returns the number of patterns. This is the same as the arity of the constructor used to |
@@ -765,9 +750,14 @@ impl Fields { | |||
765 | } | 750 | } |
766 | 751 | ||
767 | /// Returns the list of patterns along with the corresponding field indices. | 752 | /// Returns the list of patterns along with the corresponding field indices. |
768 | fn patterns_and_indices(&self) -> SmallVec<[(usize, PatId); 2]> { | 753 | fn patterns_and_indices(&self) -> SmallVec<[(LocalFieldId, PatId); 2]> { |
769 | match self { | 754 | match self { |
770 | Fields::Vec(pats) => pats.iter().copied().enumerate().collect(), | 755 | Fields::Vec(pats) => pats |
756 | .iter() | ||
757 | .copied() | ||
758 | .enumerate() | ||
759 | .map(|(i, p)| (LocalFieldId::from_raw((i as u32).into()), p)) | ||
760 | .collect(), | ||
771 | } | 761 | } |
772 | } | 762 | } |
773 | 763 | ||
@@ -779,8 +769,13 @@ impl Fields { | |||
779 | 769 | ||
780 | /// Overrides some of the fields with the provided patterns. Exactly like | 770 | /// Overrides some of the fields with the provided patterns. Exactly like |
781 | /// `replace_fields_indexed`, except that it takes `FieldPat`s as input. | 771 | /// `replace_fields_indexed`, except that it takes `FieldPat`s as input. |
782 | fn replace_with_fieldpats(&self, new_pats: impl IntoIterator<Item = PatId>) -> Self { | 772 | fn replace_with_fieldpats( |
783 | self.replace_fields_indexed(new_pats.into_iter().enumerate()) | 773 | &self, |
774 | new_pats: impl IntoIterator<Item = (LocalFieldId, PatId)>, | ||
775 | ) -> Self { | ||
776 | self.replace_fields_indexed( | ||
777 | new_pats.into_iter().map(|(field, pat)| (u32::from(field.into_raw()) as usize, pat)), | ||
778 | ) | ||
784 | } | 779 | } |
785 | 780 | ||
786 | /// Overrides some of the fields with the provided patterns. This is used when a pattern | 781 | /// Overrides some of the fields with the provided patterns. This is used when a pattern |
@@ -814,10 +809,7 @@ impl Fields { | |||
814 | let tys: SmallVec<[Ty; 2]> = match self { | 809 | let tys: SmallVec<[Ty; 2]> = match self { |
815 | Fields::Vec(pats) => pats.iter().copied().map(|pat| cx.type_of(pat)).collect(), | 810 | Fields::Vec(pats) => pats.iter().copied().map(|pat| cx.type_of(pat)).collect(), |
816 | }; | 811 | }; |
817 | pats.into_iter() | 812 | pats.into_iter().zip(tys.into_iter()).map(move |(pat, ty)| cx.alloc_pat(pat)).collect() |
818 | .zip(tys.into_iter()) | ||
819 | .map(move |(pat, ty)| cx.alloc_pat(pat, &ty)) | ||
820 | .collect() | ||
821 | }; | 813 | }; |
822 | 814 | ||
823 | match self { | 815 | match self { |
@@ -845,42 +837,24 @@ impl Fields { | |||
845 | pat: PatId, | 837 | pat: PatId, |
846 | cx: &MatchCheckCtx<'_>, | 838 | cx: &MatchCheckCtx<'_>, |
847 | ) -> Self { | 839 | ) -> Self { |
848 | match &cx.pattern_arena.borrow()[pat] { | 840 | // TODO: these alocations are so unfortunate (+1 for switching to references) |
849 | Pat::Ref { pat: subpattern, .. } | Pat::Box { inner: subpattern } => { | 841 | match cx.pattern_arena.borrow()[pat].kind.as_ref() { |
842 | PatKind::Deref { subpattern } => { | ||
850 | assert_eq!(self.len(), 1); | 843 | assert_eq!(self.len(), 1); |
851 | Fields::from_single_pattern(*subpattern) | 844 | let subpattern = cx.pattern_arena.borrow_mut().alloc(subpattern.clone()); |
845 | Fields::from_single_pattern(subpattern) | ||
852 | } | 846 | } |
853 | Pat::Tuple { args, ellipsis } | Pat::TupleStruct { args, ellipsis, .. } => { | 847 | PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { |
854 | // FIXME(iDawer) handle ellipsis. | 848 | let subpatterns = subpatterns.iter().map(|field_pat| { |
855 | // XXX(iDawer): in rustc, this is handled by HIR->TypedHIR lowering | 849 | ( |
856 | // rustc_mir_build::thir::pattern::PatCtxt::lower_tuple_subpats(..) | 850 | field_pat.field, |
857 | self.replace_with_fieldpats(args.iter().copied()) | 851 | cx.pattern_arena.borrow_mut().alloc(field_pat.pattern.clone()), |
858 | } | 852 | ) |
859 | Pat::Record { args, ellipsis, .. } => { | ||
860 | let variant_id = | ||
861 | cx.infer.variant_resolution_for_pat(pat).unwrap_or_else(|| todo!()); | ||
862 | let variant_data = variant_id.variant_data(cx.db.upcast()); | ||
863 | |||
864 | let new_pats = args.iter().map(|field_pat| { | ||
865 | // TODO: field lookup is inefficient | ||
866 | let raw = | ||
867 | variant_data.field(&field_pat.name).unwrap_or_else(|| todo!()).into_raw(); | ||
868 | let idx = u32::from(raw) as usize; | ||
869 | (idx, field_pat.pat) | ||
870 | }); | 853 | }); |
871 | self.replace_fields_indexed(new_pats) | 854 | self.replace_with_fieldpats(subpatterns) |
872 | } | ||
873 | Pat::Slice { .. } => { | ||
874 | todo!() | ||
875 | } | 855 | } |
876 | Pat::Missing | 856 | |
877 | | Pat::Wild | 857 | PatKind::Wild | PatKind::Binding { .. } | PatKind::Or { .. } => self.clone(), |
878 | | Pat::Or(_) | ||
879 | | Pat::Range { .. } | ||
880 | | Pat::Path(_) | ||
881 | | Pat::Lit(_) | ||
882 | | Pat::Bind { .. } | ||
883 | | Pat::ConstBlock(_) => self.clone(), | ||
884 | } | 858 | } |
885 | } | 859 | } |
886 | } | 860 | } |
diff --git a/crates/hir_ty/src/diagnostics/pattern/pat_util.rs b/crates/hir_ty/src/diagnostics/pattern/pat_util.rs new file mode 100644 index 000000000..f8ad4e7c6 --- /dev/null +++ b/crates/hir_ty/src/diagnostics/pattern/pat_util.rs | |||
@@ -0,0 +1,52 @@ | |||
1 | use std::iter::{Enumerate, ExactSizeIterator}; | ||
2 | |||
3 | pub struct EnumerateAndAdjust<I> { | ||
4 | enumerate: Enumerate<I>, | ||
5 | gap_pos: usize, | ||
6 | gap_len: usize, | ||
7 | } | ||
8 | |||
9 | impl<I> Iterator for EnumerateAndAdjust<I> | ||
10 | where | ||
11 | I: Iterator, | ||
12 | { | ||
13 | type Item = (usize, <I as Iterator>::Item); | ||
14 | |||
15 | fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> { | ||
16 | self.enumerate | ||
17 | .next() | ||
18 | .map(|(i, elem)| (if i < self.gap_pos { i } else { i + self.gap_len }, elem)) | ||
19 | } | ||
20 | |||
21 | fn size_hint(&self) -> (usize, Option<usize>) { | ||
22 | self.enumerate.size_hint() | ||
23 | } | ||
24 | } | ||
25 | |||
26 | pub trait EnumerateAndAdjustIterator { | ||
27 | fn enumerate_and_adjust( | ||
28 | self, | ||
29 | expected_len: usize, | ||
30 | gap_pos: Option<usize>, | ||
31 | ) -> EnumerateAndAdjust<Self> | ||
32 | where | ||
33 | Self: Sized; | ||
34 | } | ||
35 | |||
36 | impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T { | ||
37 | fn enumerate_and_adjust( | ||
38 | self, | ||
39 | expected_len: usize, | ||
40 | gap_pos: Option<usize>, | ||
41 | ) -> EnumerateAndAdjust<Self> | ||
42 | where | ||
43 | Self: Sized, | ||
44 | { | ||
45 | let actual_len = self.len(); | ||
46 | EnumerateAndAdjust { | ||
47 | enumerate: self.enumerate(), | ||
48 | gap_pos: gap_pos.unwrap_or(expected_len), | ||
49 | gap_len: expected_len - actual_len, | ||
50 | } | ||
51 | } | ||
52 | } | ||
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 | } |