mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-23 21:23:20 +00:00
internal: implement pattern adjustments.
This commit is contained in:
parent
99516bbd67
commit
0a8c30a96f
@ -100,10 +100,19 @@ impl<'a> PatCtxt<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_pattern(&mut self, pat: hir_def::expr::PatId) -> Pat {
|
pub(crate) fn lower_pattern(&mut self, pat: hir_def::expr::PatId) -> Pat {
|
||||||
// FIXME: implement pattern adjustments (implicit pattern dereference; "RFC 2005-match-ergonomics")
|
// 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.
|
||||||
|
// Pattern adjustment is part of RFC 2005-match-ergonomics.
|
||||||
// More info https://github.com/rust-lang/rust/issues/42640#issuecomment-313535089
|
// More info https://github.com/rust-lang/rust/issues/42640#issuecomment-313535089
|
||||||
let unadjusted_pat = self.lower_pattern_unadjusted(pat);
|
let unadjusted_pat = self.lower_pattern_unadjusted(pat);
|
||||||
unadjusted_pat
|
self.infer.pat_adjustments.get(&pat).map(|it| &**it).unwrap_or_default().iter().rev().fold(
|
||||||
|
unadjusted_pat,
|
||||||
|
|subpattern, ref_ty| Pat {
|
||||||
|
ty: ref_ty.clone(),
|
||||||
|
kind: Box::new(PatKind::Deref { subpattern }),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat {
|
fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat {
|
||||||
@ -1236,6 +1245,21 @@ fn main(f: Foo) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_ergonomics_issue_9095() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
enum Foo<T> { A(T) }
|
||||||
|
fn main() {
|
||||||
|
match &Foo::A(true) {
|
||||||
|
_ => {}
|
||||||
|
Foo::A(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
mod false_negatives {
|
mod false_negatives {
|
||||||
//! The implementation of match checking here is a work in progress. As we roll this out, we
|
//! The implementation of match checking here is a work in progress. As we roll this out, we
|
||||||
//! prefer false negatives to false positives (ideally there would be no false positives). This
|
//! prefer false negatives to false positives (ideally there would be no false positives). This
|
||||||
|
@ -150,6 +150,8 @@ pub struct InferenceResult {
|
|||||||
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
|
||||||
/// Interned Unknown to return references to.
|
/// Interned Unknown to return references to.
|
||||||
standard_types: InternedStandardTypes,
|
standard_types: InternedStandardTypes,
|
||||||
|
/// Stores the types which were implicitly dereferenced in pattern binding modes.
|
||||||
|
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InferenceResult {
|
impl InferenceResult {
|
||||||
|
@ -101,7 +101,9 @@ impl<'a> InferenceContext<'a> {
|
|||||||
let mut expected = self.resolve_ty_shallow(expected);
|
let mut expected = self.resolve_ty_shallow(expected);
|
||||||
|
|
||||||
if is_non_ref_pat(&body, pat) {
|
if is_non_ref_pat(&body, pat) {
|
||||||
|
let mut pat_adjustments = Vec::new();
|
||||||
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
|
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
|
||||||
|
pat_adjustments.push(expected.clone());
|
||||||
expected = self.resolve_ty_shallow(inner);
|
expected = self.resolve_ty_shallow(inner);
|
||||||
default_bm = match default_bm {
|
default_bm = match default_bm {
|
||||||
BindingMode::Move => BindingMode::Ref(mutability),
|
BindingMode::Move => BindingMode::Ref(mutability),
|
||||||
@ -109,6 +111,11 @@ impl<'a> InferenceContext<'a> {
|
|||||||
BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability),
|
BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !pat_adjustments.is_empty() {
|
||||||
|
pat_adjustments.shrink_to_fit();
|
||||||
|
self.result.pat_adjustments.insert(pat, pat_adjustments);
|
||||||
|
}
|
||||||
} else if let Pat::Ref { .. } = &body[pat] {
|
} else if let Pat::Ref { .. } = &body[pat] {
|
||||||
cov_mark::hit!(match_ergonomics_ref);
|
cov_mark::hit!(match_ergonomics_ref);
|
||||||
// When you encounter a `&pat` pattern, reset to Move.
|
// When you encounter a `&pat` pattern, reset to Move.
|
||||||
|
Loading…
Reference in New Issue
Block a user