diff options
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs')
-rw-r--r-- | crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs | 123 |
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 @@ | |||
1 | use hir_def::{ | 1 | use 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 | } |