File tree Expand file tree Collapse file tree 3 files changed +35
-2
lines changed
Expand file tree Collapse file tree 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> {
100100 }
101101
102102 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.
104107 // More info https://github.com/rust-lang/rust/issues/42640#issuecomment-313535089
105108 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+ )
107116 }
108117
109118 fn lower_pattern_unadjusted ( & mut self , pat : hir_def:: expr:: PatId ) -> Pat {
@@ -1236,6 +1245,21 @@ fn main(f: Foo) {
12361245 ) ;
12371246 }
12381247
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+
12391263 mod false_negatives {
12401264 //! The implementation of match checking here is a work in progress. As we roll this out, we
12411265 //! 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 {
150150 type_mismatches : FxHashMap < ExprOrPatId , TypeMismatch > ,
151151 /// Interned Unknown to return references to.
152152 standard_types : InternedStandardTypes ,
153+ /// Stores the types which were implicitly dereferenced in pattern binding modes.
154+ pub pat_adjustments : FxHashMap < PatId , Vec < Ty > > ,
153155}
154156
155157impl InferenceResult {
Original file line number Diff line number Diff line change @@ -101,14 +101,21 @@ impl<'a> InferenceContext<'a> {
101101 let mut expected = self . resolve_ty_shallow ( expected) ;
102102
103103 if is_non_ref_pat ( & body, pat) {
104+ let mut pat_adjustments = Vec :: new ( ) ;
104105 while let Some ( ( inner, _lifetime, mutability) ) = expected. as_reference ( ) {
106+ pat_adjustments. push ( expected. clone ( ) ) ;
105107 expected = self . resolve_ty_shallow ( inner) ;
106108 default_bm = match default_bm {
107109 BindingMode :: Move => BindingMode :: Ref ( mutability) ,
108110 BindingMode :: Ref ( Mutability :: Not ) => BindingMode :: Ref ( Mutability :: Not ) ,
109111 BindingMode :: Ref ( Mutability :: Mut ) => BindingMode :: Ref ( mutability) ,
110112 }
111113 }
114+
115+ if !pat_adjustments. is_empty ( ) {
116+ pat_adjustments. shrink_to_fit ( ) ;
117+ self . result . pat_adjustments . insert ( pat, pat_adjustments) ;
118+ }
112119 } else if let Pat :: Ref { .. } = & body[ pat] {
113120 cov_mark:: hit!( match_ergonomics_ref) ;
114121 // When you encounter a `&pat` pattern, reset to Move.
You can’t perform that action at this time.
0 commit comments