mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Respect binding mode of a binding pattern for exhaustiveness check
This commit is contained in:
parent
b17aefb83a
commit
a9ad7be748
@ -11,8 +11,11 @@ pub(crate) mod deconstruct_pat;
|
|||||||
pub(crate) mod usefulness;
|
pub(crate) mod usefulness;
|
||||||
|
|
||||||
use hir_def::{body::Body, expr::PatId, EnumVariantId, LocalFieldId, VariantId};
|
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;
|
use self::pat_util::EnumerateAndAdjustIterator;
|
||||||
|
|
||||||
@ -21,6 +24,7 @@ pub(crate) use self::usefulness::MatchArm;
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum PatternError {
|
pub(crate) enum PatternError {
|
||||||
Unimplemented,
|
Unimplemented,
|
||||||
|
UnexpectedType,
|
||||||
UnresolvedVariant,
|
UnresolvedVariant,
|
||||||
MissingField,
|
MissingField,
|
||||||
ExtraFields,
|
ExtraFields,
|
||||||
@ -129,9 +133,16 @@ impl<'a> PatCtxt<'a> {
|
|||||||
PatKind::Leaf { subpatterns }
|
PatKind::Leaf { subpatterns }
|
||||||
}
|
}
|
||||||
|
|
||||||
hir_def::expr::Pat::Bind { subpat, .. } => {
|
hir_def::expr::Pat::Bind { ref name, subpat, .. } => {
|
||||||
if let TyKind::Ref(.., rty) = ty.kind(Interner) {
|
let bm = self.infer.pat_binding_modes[&pat];
|
||||||
ty = rty;
|
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) }
|
PatKind::Binding { subpattern: self.lower_opt_pattern(subpat) }
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl_from!(ExprId, PatId for ExprOrPatId);
|
|||||||
/// Binding modes inferred for patterns.
|
/// Binding modes inferred for patterns.
|
||||||
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
|
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
enum BindingMode {
|
pub enum BindingMode {
|
||||||
Move,
|
Move,
|
||||||
Ref(Mutability),
|
Ref(Mutability),
|
||||||
}
|
}
|
||||||
@ -292,6 +292,7 @@ pub struct InferenceResult {
|
|||||||
standard_types: InternedStandardTypes,
|
standard_types: InternedStandardTypes,
|
||||||
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
||||||
pub pat_adjustments: FxHashMap<PatId, Vec<Adjustment>>,
|
pub pat_adjustments: FxHashMap<PatId, Vec<Adjustment>>,
|
||||||
|
pub pat_binding_modes: FxHashMap<PatId, BindingMode>,
|
||||||
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
|
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +204,8 @@ impl<'a> InferenceContext<'a> {
|
|||||||
} else {
|
} else {
|
||||||
BindingMode::convert(*mode)
|
BindingMode::convert(*mode)
|
||||||
};
|
};
|
||||||
|
self.result.pat_binding_modes.insert(pat, mode);
|
||||||
|
|
||||||
let inner_ty = match subpat {
|
let inner_ty = match subpat {
|
||||||
Some(subpat) => self.infer_pat(*subpat, &expected, default_bm),
|
Some(subpat) => self.infer_pat(*subpat, &expected, default_bm),
|
||||||
None => expected,
|
None => expected,
|
||||||
|
@ -883,7 +883,20 @@ static __: () = {
|
|||||||
match &n { Next(E::Foo | E::Bar) => {} }
|
match &n { Next(E::Foo | E::Bar) => {} }
|
||||||
match &n { _ | Next(E::Bar) => {} }
|
match &n { _ | Next(E::Bar) => {} }
|
||||||
};",
|
};",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn binding_mode_by_ref() {
|
||||||
|
check_diagnostics_no_bails(
|
||||||
|
r"
|
||||||
|
enum E{ A, B }
|
||||||
|
fn foo() {
|
||||||
|
match &E::A {
|
||||||
|
E::A => {}
|
||||||
|
x => {}
|
||||||
|
}
|
||||||
|
}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user