Lower binding pattern

This commit is contained in:
Dawer 2021-05-07 10:38:51 +05:00
parent cf6f989a8d
commit a236bfa57a
2 changed files with 28 additions and 9 deletions

View file

@ -11,7 +11,7 @@ use la_arena::Idx;
use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, Substitution, Ty, TyKind}; use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, Substitution, Ty, TyKind};
use self::{deconstruct_pat::ToDo, pat_util::EnumerateAndAdjustIterator}; use self::pat_util::EnumerateAndAdjustIterator;
pub type PatId = Idx<Pat>; pub type PatId = Idx<Pat>;
@ -45,7 +45,6 @@ pub enum PatKind {
/// `x`, `ref x`, `x @ P`, etc. /// `x`, `ref x`, `x @ P`, etc.
Binding { Binding {
subpattern: Option<Pat>, subpattern: Option<Pat>,
// todo: ToDo,
}, },
/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
@ -119,6 +118,10 @@ impl<'a> PatCtxt<'a> {
PatKind::Leaf { subpatterns } PatKind::Leaf { subpatterns }
} }
hir_def::expr::Pat::Bind { subpat, .. } => {
PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) }
}
hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } => { hir_def::expr::Pat::TupleStruct { ref args, ellipsis, .. } => {
let variant_data = match self.infer.variant_resolution_for_pat(pat) { let variant_data = match self.infer.variant_resolution_for_pat(pat) {
Some(variant_id) => variant_id.variant_data(self.db.upcast()), Some(variant_id) => variant_id.variant_data(self.db.upcast()),
@ -175,6 +178,10 @@ impl<'a> PatCtxt<'a> {
pats.iter().map(|&p| self.lower_pattern(p)).collect() pats.iter().map(|&p| self.lower_pattern(p)).collect()
} }
fn lower_opt_pattern(&mut self, pat: Option<hir_def::expr::PatId>) -> Option<Pat> {
pat.map(|p| self.lower_pattern(p))
}
fn lower_variant_or_leaf( fn lower_variant_or_leaf(
&mut self, &mut self,
pat: hir_def::expr::PatId, pat: hir_def::expr::PatId,
@ -383,13 +390,30 @@ fn main() {
struct S { a: char} struct S { a: char}
fn main(v: S) { fn main(v: S) {
match v { S{ a } => {} } match v { S{ a } => {} }
match v { S{ a: x } => {} } match v { S{ a: _x } => {} }
match v { S{ a: 'a' } => {} } match v { S{ a: 'a' } => {} }
match v { S{..} => {} } match v { S{..} => {} }
match v { _ => {} } match v { _ => {} }
match v { } match v { }
//^ Missing match arm //^ Missing match arm
} }
"#,
);
}
#[test]
fn binding() {
check_diagnostics(
r#"
fn main() {
match true {
_x @ true => {}
false => {}
}
//FIXME: false negative.
// Binding patterns should be expanded in `usefulness::expand_pattern()`
match true { _x @ true => {} }
}
"#, "#,
); );
} }

View file

@ -801,12 +801,7 @@ impl Fields {
cx: &MatchCheckCtx<'_>, cx: &MatchCheckCtx<'_>,
pats: impl IntoIterator<Item = Pat>, pats: impl IntoIterator<Item = Pat>,
) -> Self { ) -> Self {
let pats = { let pats = pats.into_iter().map(|pat| cx.alloc_pat(pat)).collect();
let tys: SmallVec<[Ty; 2]> = match self {
Fields::Vec(pats) => pats.iter().copied().map(|pat| cx.type_of(pat)).collect(),
};
pats.into_iter().zip(tys.into_iter()).map(move |(pat, ty)| cx.alloc_pat(pat)).collect()
};
match self { match self {
Fields::Vec(_) => Fields::Vec(pats), Fields::Vec(_) => Fields::Vec(pats),