Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir_ty/src/diagnostics/match_check.rs')
| -rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index b3cc83b340..87a8579761 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -5,25 +5,26 @@ //! //! It is modeled on the rustc module `rustc_mir_build::thir::pattern`. -mod deconstruct_pat; mod pat_util; +pub(crate) mod deconstruct_pat; pub(crate) mod usefulness; -use hir_def::{body::Body, EnumVariantId, LocalFieldId, VariantId}; -use la_arena::Idx; +use hir_def::{body::Body, expr::PatId, EnumVariantId, LocalFieldId, VariantId}; +use stdx::never; -use crate::{db::HirDatabase, InferenceResult, Interner, Substitution, Ty, TyKind}; +use crate::{ + db::HirDatabase, infer::BindingMode, InferenceResult, Interner, Substitution, Ty, TyKind, +}; use self::pat_util::EnumerateAndAdjustIterator; pub(crate) use self::usefulness::MatchArm; -pub(crate) type PatId = Idx<Pat>; - #[derive(Clone, Debug)] pub(crate) enum PatternError { Unimplemented, + UnexpectedType, UnresolvedVariant, MissingField, ExtraFields, @@ -41,12 +42,6 @@ pub(crate) struct Pat { pub(crate) kind: Box<PatKind>, } -impl Pat { - pub(crate) fn wildcard_from_ty(ty: Ty) -> Self { - Pat { ty, kind: Box::new(PatKind::Wild) } - } -} - /// Close relative to `rustc_mir_build::thir::pattern::PatKind` #[derive(Clone, Debug, PartialEq)] pub(crate) enum PatKind { @@ -100,7 +95,7 @@ impl<'a> PatCtxt<'a> { Self { db, infer, body, errors: Vec::new() } } - pub(crate) fn lower_pattern(&mut self, pat: hir_def::expr::PatId) -> Pat { + pub(crate) fn lower_pattern(&mut self, pat: PatId) -> Pat { // XXX(iDawer): Collecting pattern adjustments feels imprecise to me. // When lowering of & and box patterns are implemented this should be tested // in a manner of `match_ergonomics_issue_9095` test. @@ -116,7 +111,7 @@ impl<'a> PatCtxt<'a> { ) } - fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { + fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat { let mut ty = &self.infer[pat]; let variant = self.infer.variant_resolution_for_pat(pat); @@ -138,9 +133,16 @@ impl<'a> PatCtxt<'a> { PatKind::Leaf { subpatterns } } - hir_def::expr::Pat::Bind { subpat, .. } => { - if let TyKind::Ref(.., rty) = ty.kind(Interner) { - ty = rty; + hir_def::expr::Pat::Bind { ref name, subpat, .. } => { + let bm = self.infer.pat_binding_modes[&pat]; + match (bm, ty.kind(Interner)) { + (BindingMode::Ref(_), TyKind::Ref(.., rty)) => ty = rty, + (BindingMode::Ref(_), _) => { + never!("`ref {}` has wrong type {:?}", name, ty); + self.errors.push(PatternError::UnexpectedType); + return Pat { ty: ty.clone(), kind: PatKind::Wild.into() }; + } + _ => (), } PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) } } @@ -189,7 +191,7 @@ impl<'a> PatCtxt<'a> { fn lower_tuple_subpats( &mut self, - pats: &[hir_def::expr::PatId], + pats: &[PatId], expected_len: usize, ellipsis: Option<usize>, ) -> Vec<FieldPat> { @@ -207,17 +209,17 @@ impl<'a> PatCtxt<'a> { .collect() } - fn lower_patterns(&mut self, pats: &[hir_def::expr::PatId]) -> Vec<Pat> { + fn lower_patterns(&mut self, pats: &[PatId]) -> Vec<Pat> { pats.iter().map(|&p| self.lower_pattern(p)).collect() } - fn lower_opt_pattern(&mut self, pat: Option<hir_def::expr::PatId>) -> Option<Pat> { + fn lower_opt_pattern(&mut self, pat: Option<PatId>) -> Option<Pat> { pat.map(|p| self.lower_pattern(p)) } fn lower_variant_or_leaf( &mut self, - pat: hir_def::expr::PatId, + pat: PatId, ty: &Ty, subpatterns: Vec<FieldPat>, ) -> PatKind { @@ -244,7 +246,7 @@ impl<'a> PatCtxt<'a> { kind } - fn lower_path(&mut self, pat: hir_def::expr::PatId, _path: &hir_def::path::Path) -> Pat { + fn lower_path(&mut self, pat: PatId, _path: &hir_def::path::Path) -> Pat { let ty = &self.infer[pat]; let pat_from_kind = |kind| Pat { ty: ty.clone(), kind: Box::new(kind) }; |