File tree 3 files changed +35
-2
lines changed
3 files changed +35
-2
lines changed Original file line number Diff line number Diff line change @@ -100,10 +100,19 @@ impl<'a> PatCtxt<'a> {
100
100
}
101
101
102
102
pub ( crate ) fn lower_pattern ( & mut self , pat : hir_def:: expr:: PatId ) -> Pat {
103
- // FIXME: implement pattern adjustments (implicit pattern dereference; "RFC 2005-match-ergonomics")
103
+ // XXX(iDawer): Collecting pattern adjustments feels imprecise to me.
104
+ // When lowering of & and box patterns are implemented this should be tested
105
+ // in a manner of `match_ergonomics_issue_9095` test.
106
+ // Pattern adjustment is part of RFC 2005-match-ergonomics.
104
107
// More info https://github.com/rust-lang/rust/issues/42640#issuecomment-313535089
105
108
let unadjusted_pat = self . lower_pattern_unadjusted ( pat) ;
106
- unadjusted_pat
109
+ self . infer . pat_adjustments . get ( & pat) . map ( |it| & * * it) . unwrap_or_default ( ) . iter ( ) . rev ( ) . fold (
110
+ unadjusted_pat,
111
+ |subpattern, ref_ty| Pat {
112
+ ty : ref_ty. clone ( ) ,
113
+ kind : Box :: new ( PatKind :: Deref { subpattern } ) ,
114
+ } ,
115
+ )
107
116
}
108
117
109
118
fn lower_pattern_unadjusted ( & mut self , pat : hir_def:: expr:: PatId ) -> Pat {
@@ -1236,6 +1245,21 @@ fn main(f: Foo) {
1236
1245
) ;
1237
1246
}
1238
1247
1248
+ #[ test]
1249
+ fn match_ergonomics_issue_9095 ( ) {
1250
+ check_diagnostics (
1251
+ r#"
1252
+ enum Foo<T> { A(T) }
1253
+ fn main() {
1254
+ match &Foo::A(true) {
1255
+ _ => {}
1256
+ Foo::A(_) => {}
1257
+ }
1258
+ }
1259
+ "# ,
1260
+ ) ;
1261
+ }
1262
+
1239
1263
mod false_negatives {
1240
1264
//! The implementation of match checking here is a work in progress. As we roll this out, we
1241
1265
//! prefer false negatives to false positives (ideally there would be no false positives). This
Original file line number Diff line number Diff line change @@ -150,6 +150,8 @@ pub struct InferenceResult {
150
150
type_mismatches : FxHashMap < ExprOrPatId , TypeMismatch > ,
151
151
/// Interned Unknown to return references to.
152
152
standard_types : InternedStandardTypes ,
153
+ /// Stores the types which were implicitly dereferenced in pattern binding modes.
154
+ pub pat_adjustments : FxHashMap < PatId , Vec < Ty > > ,
153
155
}
154
156
155
157
impl InferenceResult {
Original file line number Diff line number Diff line change @@ -101,14 +101,21 @@ impl<'a> InferenceContext<'a> {
101
101
let mut expected = self . resolve_ty_shallow ( expected) ;
102
102
103
103
if is_non_ref_pat ( & body, pat) {
104
+ let mut pat_adjustments = Vec :: new ( ) ;
104
105
while let Some ( ( inner, _lifetime, mutability) ) = expected. as_reference ( ) {
106
+ pat_adjustments. push ( expected. clone ( ) ) ;
105
107
expected = self . resolve_ty_shallow ( inner) ;
106
108
default_bm = match default_bm {
107
109
BindingMode :: Move => BindingMode :: Ref ( mutability) ,
108
110
BindingMode :: Ref ( Mutability :: Not ) => BindingMode :: Ref ( Mutability :: Not ) ,
109
111
BindingMode :: Ref ( Mutability :: Mut ) => BindingMode :: Ref ( mutability) ,
110
112
}
111
113
}
114
+
115
+ if !pat_adjustments. is_empty ( ) {
116
+ pat_adjustments. shrink_to_fit ( ) ;
117
+ self . result . pat_adjustments . insert ( pat, pat_adjustments) ;
118
+ }
112
119
} else if let Pat :: Ref { .. } = & body[ pat] {
113
120
cov_mark:: hit!( match_ergonomics_ref) ;
114
121
// When you encounter a `&pat` pattern, reset to Move.
You can’t perform that action at this time.
0 commit comments