diff options
author | Dawer <[email protected]> | 2021-05-06 05:42:00 +0100 |
---|---|---|
committer | Dawer <[email protected]> | 2021-05-31 20:03:46 +0100 |
commit | 975109051caf05de6d166779589e299d9aca9cd5 (patch) | |
tree | 6bfbfb1e9f6ae45b2d81921bd7cf5cfe449f673f /crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs | |
parent | 2431ff5987ee1f802ede0db5eedc863ce9a8e70f (diff) |
Basic lowering hir_def::exrp::Pat -> typed HIR.
Pattern arena is broken
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs | 188 |
1 files changed, 81 insertions, 107 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 | } |