aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs123
1 files changed, 68 insertions, 55 deletions
diff --git a/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs
index c02e783af..7bd02a502 100644
--- a/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs
+++ b/crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs
@@ -1,5 +1,9 @@
1use hir_def::{ 1use hir_def::{
2 expr::{Pat, PatId}, 2 expr::{Pat, PatId, RecordFieldPat},
3 find_path::find_path,
4 item_scope::ItemInNs,
5 path::Path,
6 type_ref::Mutability,
3 AttrDefId, EnumVariantId, HasModule, VariantId, 7 AttrDefId, EnumVariantId, HasModule, VariantId,
4}; 8};
5 9
@@ -126,19 +130,25 @@ impl Constructor {
126 130
127 /// Determines the constructor that the given pattern can be specialized to. 131 /// Determines the constructor that the given pattern can be specialized to.
128 pub(super) fn from_pat(cx: &MatchCheckCtx<'_>, pat: PatId) -> Self { 132 pub(super) fn from_pat(cx: &MatchCheckCtx<'_>, pat: PatId) -> Self {
133 let ty = cx.type_of(pat);
129 match &cx.pattern_arena.borrow()[pat] { 134 match &cx.pattern_arena.borrow()[pat] {
130 Pat::Bind { .. } | Pat::Wild => Wildcard, 135 Pat::Bind { .. } | Pat::Wild => Wildcard,
131 Pat::Tuple { .. } | Pat::Ref { .. } | Pat::Box { .. } => Single, 136 Pat::Tuple { .. } | Pat::Ref { .. } | Pat::Box { .. } => Single,
137 Pat::Record { .. } | Pat::Path(_) | Pat::TupleStruct { .. } => {
138 let variant_id =
139 cx.infer.variant_resolution_for_pat(pat).unwrap_or_else(|| todo!());
140 match variant_id {
141 VariantId::EnumVariantId(id) => Variant(id),
142 VariantId::StructId(_) | VariantId::UnionId(_) => Single,
143 }
144 }
132 145
146 Pat::Or(..) => panic!("bug: Or-pattern should have been expanded earlier on."),
133 pat => todo!("Constructor::from_pat {:?}", pat), 147 pat => todo!("Constructor::from_pat {:?}", pat),
134 // Pat::Missing => {} 148 // Pat::Missing => {}
135 // Pat::Or(_) => {}
136 // Pat::Record { path, args, ellipsis } => {}
137 // Pat::Range { start, end } => {} 149 // Pat::Range { start, end } => {}
138 // Pat::Slice { prefix, slice, suffix } => {} 150 // Pat::Slice { prefix, slice, suffix } => {}
139 // Pat::Path(_) => {}
140 // Pat::Lit(_) => {} 151 // Pat::Lit(_) => {}
141 // Pat::TupleStruct { path, args, ellipsis } => {}
142 // Pat::ConstBlock(_) => {} 152 // Pat::ConstBlock(_) => {}
143 } 153 }
144 } 154 }
@@ -435,7 +445,8 @@ impl Fields {
435 } else { 445 } else {
436 let variant_id = constructor.variant_id_for_adt(*adt, cx); 446 let variant_id = constructor.variant_id_for_adt(*adt, cx);
437 let variant = variant_id.variant_data(cx.db.upcast()); 447 let variant = variant_id.variant_data(cx.db.upcast());
438 let adt_is_local = variant_id.module(cx.db.upcast()).krate() == cx.krate; 448 let adt_is_local =
449 variant_id.module(cx.db.upcast()).krate() == cx.module.krate();
439 // Whether we must not match the fields of this variant exhaustively. 450 // Whether we must not match the fields of this variant exhaustively.
440 let is_non_exhaustive = 451 let is_non_exhaustive =
441 is_field_list_non_exhaustive(variant_id, cx) && !adt_is_local; 452 is_field_list_non_exhaustive(variant_id, cx) && !adt_is_local;
@@ -490,43 +501,44 @@ impl Fields {
490 Single | Variant(_) => match pcx.ty.kind(&Interner) { 501 Single | Variant(_) => match pcx.ty.kind(&Interner) {
491 TyKind::Adt(..) | TyKind::Tuple(..) => { 502 TyKind::Adt(..) | TyKind::Tuple(..) => {
492 // We want the real indices here. 503 // We want the real indices here.
493 // TODO indices 504 // TODO indices and ellipsis interaction, tests
494 let subpatterns = subpatterns_and_indices.iter().map(|&(_, pat)| pat).collect(); 505 let subpatterns = subpatterns_and_indices.iter().map(|&(_, pat)| pat).collect();
495 506
496 if let Some((adt, substs)) = pcx.ty.as_adt() { 507 if let Some((adt, substs)) = pcx.ty.as_adt() {
497 if let hir_def::AdtId::EnumId(_) = adt { 508 let item = ItemInNs::Types(adt.into());
498 todo!() 509 let path = find_path(pcx.cx.db.upcast(), item, pcx.cx.module)
499 } else { 510 .map(|mpath| Path::from_known_path(mpath, Vec::new()).into());
500 todo!() 511 match adt {
512 hir_def::AdtId::EnumId(_) => todo!(),
513 hir_def::AdtId::StructId(id) => {
514 let variant_data = &pcx.cx.db.struct_data(id).variant_data;
515 let args = subpatterns_and_indices
516 .iter()
517 .zip(variant_data.fields().iter())
518 .map(|(&(_, pat), (_, field_data))| RecordFieldPat {
519 name: field_data.name.clone(),
520 pat,
521 })
522 .collect();
523 Pat::Record { path, args, ellipsis: false }
524 }
525 hir_def::AdtId::UnionId(_) => todo!(),
501 } 526 }
502 } else { 527 } else {
503 // TODO ellipsis
504 Pat::Tuple { args: subpatterns, ellipsis: None } 528 Pat::Tuple { args: subpatterns, ellipsis: None }
505 } 529 }
506 } 530 }
507 531 // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
508 _ => todo!(), 532 // be careful to reconstruct the correct constant pattern here. However a string
509 // TyKind::AssociatedType(_, _) => {} 533 // literal pattern will never be reported as a non-exhaustiveness witness, so we
510 // TyKind::Scalar(_) => {} 534 // can ignore this issue.
511 // TyKind::Array(_, _) => {} 535 TyKind::Ref(..) => {
512 // TyKind::Slice(_) => {} 536 Pat::Ref { pat: subpatterns.next().unwrap(), mutability: Mutability::Shared }
513 // TyKind::Raw(_, _) => {} 537 }
514 // TyKind::Ref(_, _, _) => {} 538 TyKind::Slice(..) | TyKind::Array(..) => {
515 // TyKind::OpaqueType(_, _) => {} 539 panic!("bug: bad slice pattern {:?} {:?}", ctor, pcx.ty)
516 // TyKind::FnDef(_, _) => {} 540 }
517 // TyKind::Str => {} 541 _ => Pat::Wild,
518 // TyKind::Never => {}
519 // TyKind::Closure(_, _) => {}
520 // TyKind::Generator(_, _) => {}
521 // TyKind::GeneratorWitness(_, _) => {}
522 // TyKind::Foreign(_) => {}
523 // TyKind::Error => {}
524 // TyKind::Placeholder(_) => {}
525 // TyKind::Dyn(_) => {}
526 // TyKind::Alias(_) => {}
527 // TyKind::Function(_) => {}
528 // TyKind::BoundVar(_) => {}
529 // TyKind::InferenceVar(_, _) => {}
530 }, 542 },
531 Constructor::Slice(slice) => { 543 Constructor::Slice(slice) => {
532 todo!() 544 todo!()
@@ -537,9 +549,9 @@ impl Fields {
537 NonExhaustive => Pat::Wild, 549 NonExhaustive => Pat::Wild,
538 Wildcard => Pat::Wild, 550 Wildcard => Pat::Wild,
539 Opaque => panic!("bug: we should not try to apply an opaque constructor"), 551 Opaque => panic!("bug: we should not try to apply an opaque constructor"),
540 Missing => panic!( 552 Missing => {
541 "bug: trying to apply the `Missing` constructor; this should have been done in `apply_constructors`" 553 panic!("bug: trying to apply the `Missing` constructor; this should have been done in `apply_constructors`")
542 ), 554 }
543 } 555 }
544 } 556 }
545 557
@@ -628,30 +640,31 @@ impl Fields {
628 cx: &MatchCheckCtx<'_>, 640 cx: &MatchCheckCtx<'_>,
629 ) -> Self { 641 ) -> Self {
630 match &cx.pattern_arena.borrow()[pat] { 642 match &cx.pattern_arena.borrow()[pat] {
631 Pat::Ref { pat: subpattern, .. } => { 643 Pat::Ref { pat: subpattern, .. } | Pat::Box { inner: subpattern } => {
632 assert_eq!(self.len(), 1); 644 assert_eq!(self.len(), 1);
633 Fields::from_single_pattern(*subpattern) 645 Fields::from_single_pattern(*subpattern)
634 } 646 }
635 Pat::Tuple { args: subpatterns, ellipsis } => { 647 Pat::Tuple { args, ellipsis } | Pat::TupleStruct { args, ellipsis, .. } => {
636 // FIXME(iDawer) handle ellipsis. 648 // FIXME(iDawer) handle ellipsis.
637 // XXX(iDawer): in rustc, this is handled by HIR->TypedHIR lowering 649 // XXX(iDawer): in rustc, this is handled by HIR->TypedHIR lowering
638 // rustc_mir_build::thir::pattern::PatCtxt::lower_tuple_subpats(..) 650 // rustc_mir_build::thir::pattern::PatCtxt::lower_tuple_subpats(..)
639 self.replace_with_fieldpats(subpatterns.iter().copied()) 651 self.replace_with_fieldpats(args.iter().copied())
640 } 652 }
641 653 Pat::Record { args, ellipsis, .. } => {
642 Pat::Wild => self.clone(), 654 // FIXME(iDawer) handle ellipsis.
643 pat => todo!("Fields::replace_with_pattern_arguments({:?})", pat), 655 self.replace_with_fieldpats(args.iter().map(|field_pat| field_pat.pat))
644 // Pat::Missing => {} 656 }
645 // Pat::Or(_) => {} 657 Pat::Slice { .. } => {
646 // Pat::Record { path, args, ellipsis } => {} 658 todo!()
647 // Pat::Range { start, end } => {} 659 }
648 // Pat::Slice { prefix, slice, suffix } => {} 660 Pat::Missing
649 // Pat::Path(_) => {} 661 | Pat::Wild
650 // Pat::Lit(_) => {} 662 | Pat::Or(_)
651 // Pat::Bind { mode, name, subpat } => {} 663 | Pat::Range { .. }
652 // Pat::TupleStruct { path, args, ellipsis } => {} 664 | Pat::Path(_)
653 // Pat::Box { inner } => {} 665 | Pat::Lit(_)
654 // Pat::ConstBlock(_) => {} 666 | Pat::Bind { .. }
667 | Pat::ConstBlock(_) => self.clone(),
655 } 668 }
656 } 669 }
657} 670}