aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/pattern
diff options
context:
space:
mode:
authorDawer <[email protected]>2021-04-29 19:28:43 +0100
committerDawer <[email protected]>2021-05-31 20:03:46 +0100
commit678d85ca7e4d7e631a450b8c050fe7696da0cac3 (patch)
treef013655d9c581959ebd5a2db83d6fea91005fdb6 /crates/hir_ty/src/diagnostics/pattern
parent062c7953a12bf849db641d14d8d26af47ddca79e (diff)
Implement struct ctor application
Diffstat (limited to 'crates/hir_ty/src/diagnostics/pattern')
-rw-r--r--crates/hir_ty/src/diagnostics/pattern/deconstruct_pat.rs123
-rw-r--r--crates/hir_ty/src/diagnostics/pattern/usefulness.rs8
2 files changed, 70 insertions, 61 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}
diff --git a/crates/hir_ty/src/diagnostics/pattern/usefulness.rs b/crates/hir_ty/src/diagnostics/pattern/usefulness.rs
index 2e5d2fb6c..4b55aee97 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
4use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc}; 4use std::{cell::RefCell, iter::FromIterator, ops::Index, sync::Arc};
5 5
6use base_db::CrateId; 6use hir_def::{ModuleId, body::Body, expr::{ExprId, Pat, PatId}};
7use hir_def::{
8 body::Body,
9 expr::{ExprId, Pat, PatId},
10};
11use la_arena::Arena; 7use la_arena::Arena;
12use once_cell::unsync::OnceCell; 8use once_cell::unsync::OnceCell;
13use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
@@ -24,7 +20,7 @@ use self::{
24}; 20};
25 21
26pub(crate) struct MatchCheckCtx<'a> { 22pub(crate) struct MatchCheckCtx<'a> {
27 pub(crate) krate: CrateId, 23 pub(crate) module: ModuleId,
28 pub(crate) match_expr: ExprId, 24 pub(crate) match_expr: ExprId,
29 pub(crate) body: Arc<Body>, 25 pub(crate) body: Arc<Body>,
30 pub(crate) infer: &'a InferenceResult, 26 pub(crate) infer: &'a InferenceResult,