Expand binding patterns.
This commit is contained in:
parent
d7239e5ab4
commit
9b841a9a04
@ -239,6 +239,101 @@ fn lower_lit(&mut self, expr: hir_def::expr::ExprId) -> PatKind {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait PatternFoldable: Sized {
|
||||
fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
self.super_fold_with(folder)
|
||||
}
|
||||
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self;
|
||||
}
|
||||
|
||||
pub(crate) trait PatternFolder: Sized {
|
||||
fn fold_pattern(&mut self, pattern: &Pat) -> Pat {
|
||||
pattern.super_fold_with(self)
|
||||
}
|
||||
|
||||
fn fold_pattern_kind(&mut self, kind: &PatKind) -> PatKind {
|
||||
kind.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PatternFoldable> PatternFoldable for Box<T> {
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
let content: T = (**self).fold_with(folder);
|
||||
Box::new(content)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PatternFoldable> PatternFoldable for Vec<T> {
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
self.iter().map(|t| t.fold_with(folder)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PatternFoldable> PatternFoldable for Option<T> {
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
self.as_ref().map(|t| t.fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! clone_impls {
|
||||
($($ty:ty),+) => {
|
||||
$(
|
||||
impl PatternFoldable for $ty {
|
||||
fn super_fold_with<F: PatternFolder>(&self, _: &mut F) -> Self {
|
||||
Clone::clone(self)
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
clone_impls! { LocalFieldId, Ty, Substitution, EnumVariantId }
|
||||
|
||||
impl PatternFoldable for FieldPat {
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PatternFoldable for Pat {
|
||||
fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
folder.fold_pattern(self)
|
||||
}
|
||||
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
Pat { ty: self.ty.fold_with(folder), kind: self.kind.fold_with(folder) }
|
||||
}
|
||||
}
|
||||
|
||||
impl PatternFoldable for PatKind {
|
||||
fn fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
folder.fold_pattern_kind(self)
|
||||
}
|
||||
|
||||
fn super_fold_with<F: PatternFolder>(&self, folder: &mut F) -> Self {
|
||||
match self {
|
||||
PatKind::Wild => PatKind::Wild,
|
||||
PatKind::Binding { subpattern } => {
|
||||
PatKind::Binding { subpattern: subpattern.fold_with(folder) }
|
||||
}
|
||||
PatKind::Variant { substs, enum_variant, subpatterns } => PatKind::Variant {
|
||||
substs: substs.fold_with(folder),
|
||||
enum_variant: enum_variant.fold_with(folder),
|
||||
subpatterns: subpatterns.fold_with(folder),
|
||||
},
|
||||
PatKind::Leaf { subpatterns } => {
|
||||
PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) }
|
||||
}
|
||||
PatKind::Deref { subpattern } => {
|
||||
PatKind::Deref { subpattern: subpattern.fold_with(folder) }
|
||||
}
|
||||
&PatKind::LiteralBool { value } => PatKind::LiteralBool { value },
|
||||
PatKind::Or { pats } => PatKind::Or { pats: pats.fold_with(folder) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::diagnostics::tests::check_diagnostics;
|
||||
@ -410,9 +505,8 @@ fn main() {
|
||||
_x @ true => {}
|
||||
false => {}
|
||||
}
|
||||
//FIXME: false negative.
|
||||
// Binding patterns should be expanded in `usefulness::expand_pattern()`
|
||||
match true { _x @ true => {} }
|
||||
//^^^^ Missing match arm
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -9,11 +9,11 @@
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::{db::HirDatabase, InferenceResult, Ty};
|
||||
use crate::{db::HirDatabase, InferenceResult, Interner, Ty};
|
||||
|
||||
use super::{
|
||||
deconstruct_pat::{Constructor, Fields, SplitWildcard},
|
||||
Pat, PatId, PatKind,
|
||||
Pat, PatId, PatKind, PatternFoldable, PatternFolder,
|
||||
};
|
||||
|
||||
use self::{
|
||||
@ -75,8 +75,18 @@ pub(super) struct PatCtxt<'a> {
|
||||
}
|
||||
|
||||
pub(crate) fn expand_pattern(pat: Pat) -> Pat {
|
||||
// TODO: LiteralExpander, it is about string literal patterns
|
||||
pat
|
||||
LiteralExpander.fold_pattern(&pat)
|
||||
}
|
||||
|
||||
struct LiteralExpander;
|
||||
|
||||
impl PatternFolder for LiteralExpander {
|
||||
fn fold_pattern(&mut self, pat: &Pat) -> Pat {
|
||||
match (pat.ty.kind(&Interner), pat.kind.as_ref()) {
|
||||
(_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self),
|
||||
_ => pat.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pat {
|
||||
|
Loading…
Reference in New Issue
Block a user