mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +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;
|
||||
|
||||
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;
|
||||
|
||||
@ -21,6 +24,7 @@ pub(crate) use self::usefulness::MatchArm;
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum PatternError {
|
||||
Unimplemented,
|
||||
UnexpectedType,
|
||||
UnresolvedVariant,
|
||||
MissingField,
|
||||
ExtraFields,
|
||||
@ -129,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) }
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl_from!(ExprId, PatId for ExprOrPatId);
|
||||
/// Binding modes inferred for patterns.
|
||||
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
enum BindingMode {
|
||||
pub enum BindingMode {
|
||||
Move,
|
||||
Ref(Mutability),
|
||||
}
|
||||
@ -292,6 +292,7 @@ pub struct InferenceResult {
|
||||
standard_types: InternedStandardTypes,
|
||||
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
||||
pub pat_adjustments: FxHashMap<PatId, Vec<Adjustment>>,
|
||||
pub pat_binding_modes: FxHashMap<PatId, BindingMode>,
|
||||
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,8 @@ impl<'a> InferenceContext<'a> {
|
||||
} else {
|
||||
BindingMode::convert(*mode)
|
||||
};
|
||||
self.result.pat_binding_modes.insert(pat, mode);
|
||||
|
||||
let inner_ty = match subpat {
|
||||
Some(subpat) => self.infer_pat(*subpat, &expected, default_bm),
|
||||
None => expected,
|
||||
|
@ -883,7 +883,20 @@ static __: () = {
|
||||
match &n { Next(E::Foo | 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