]> git.lizzy.rs Git - rust.git/commitdiff
typeck/pat.rs: extract `check_pat_ref`.
authorMazdak Farrokhzad <twingoow@gmail.com>
Sat, 24 Aug 2019 02:45:59 +0000 (04:45 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Sat, 24 Aug 2019 17:15:36 +0000 (19:15 +0200)
src/librustc_typeck/check/pat.rs

index f740dc73db5402bfb1cc4848531f501d5dc4e282..55a9360b83f190bbea1caa4bfdbd755a9d010103 100644 (file)
@@ -111,50 +111,7 @@ pub fn check_pat_walk(
                 self.check_pat_box(pat.span, inner, expected, def_bm, discrim_span)
             }
             PatKind::Ref(ref inner, mutbl) => {
-                let expected = self.shallow_resolve(expected);
-                if self.check_dereferencable(pat.span, expected, &inner) {
-                    // `demand::subtype` would be good enough, but using
-                    // `eqtype` turns out to be equally general. See (*)
-                    // below for details.
-
-                    // Take region, inner-type from expected type if we
-                    // can, to avoid creating needless variables.  This
-                    // also helps with the bad interactions of the given
-                    // hack detailed in (*) below.
-                    debug!("check_pat_walk: expected={:?}", expected);
-                    let (rptr_ty, inner_ty) = match expected.sty {
-                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
-                            (expected, r_ty)
-                        }
-                        _ => {
-                            let inner_ty = self.next_ty_var(
-                                TypeVariableOrigin {
-                                    kind: TypeVariableOriginKind::TypeInference,
-                                    span: inner.span,
-                                }
-                            );
-                            let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
-                            let region = self.next_region_var(infer::PatternRegion(pat.span));
-                            let rptr_ty = tcx.mk_ref(region, mt);
-                            debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
-                            let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
-
-                            // Look for a case like `fn foo(&foo: u32)` and suggest
-                            // `fn foo(foo: &u32)`
-                            if let Some(mut err) = err {
-                                self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
-                                err.emit();
-                            }
-                            (rptr_ty, inner_ty)
-                        }
-                    };
-
-                    self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
-                    rptr_ty
-                } else {
-                    self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
-                    tcx.types.err
-                }
+                self.check_pat_ref(pat, inner, mutbl, expected, def_bm, discrim_span)
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
@@ -1059,4 +1016,58 @@ fn check_pat_box(
             tcx.types.err
         }
     }
+
+    fn check_pat_ref(
+        &self,
+        pat: &hir::Pat,
+        inner: &'tcx hir::Pat,
+        mutbl: hir::Mutability,
+        expected: Ty<'tcx>,
+        def_bm: ty::BindingMode,
+        discrim_span: Option<Span>,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx;
+        let expected = self.shallow_resolve(expected);
+        if self.check_dereferencable(pat.span, expected, &inner) {
+            // `demand::subtype` would be good enough, but using `eqtype` turns
+            // out to be equally general. See (*) below for details.
+
+            // Take region, inner-type from expected type if we can,
+            // to avoid creating needless variables. This also helps with
+            // the bad  interactions of the given hack detailed in (*) below.
+            debug!("check_pat_ref: expected={:?}", expected);
+            let (rptr_ty, inner_ty) = match expected.sty {
+                ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
+                    (expected, r_ty)
+                }
+                _ => {
+                    let inner_ty = self.next_ty_var(
+                        TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeInference,
+                            span: inner.span,
+                        }
+                    );
+                    let mt = ty::TypeAndMut { ty: inner_ty, mutbl };
+                    let region = self.next_region_var(infer::PatternRegion(pat.span));
+                    let rptr_ty = tcx.mk_ref(region, mt);
+                    debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty);
+                    let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
+
+                    // Look for a case like `fn foo(&foo: u32)` and suggest
+                    // `fn foo(foo: &u32)`
+                    if let Some(mut err) = err {
+                        self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
+                        err.emit();
+                    }
+                    (rptr_ty, inner_ty)
+                }
+            };
+
+            self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
+            rptr_ty
+        } else {
+            self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
+            tcx.types.err
+        }
+    }
 }