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

index 9693ab57bc7deca2ada8e19e5cae68a82c388c72..fda5d3a2ecd4ab0c0cf1f1a2352145068c882e25 100644 (file)
@@ -77,53 +77,8 @@ pub fn check_pat_walk(
                 }
             }
             PatKind::Binding(ba, var_id, _, ref sub) => {
-                let bm = if ba == hir::BindingAnnotation::Unannotated {
-                    def_bm
-                } else {
-                    ty::BindingMode::convert(ba)
-                };
-                self.inh
-                    .tables
-                    .borrow_mut()
-                    .pat_binding_modes_mut()
-                    .insert(pat.hir_id, bm);
-                debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
-                let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
-                match bm {
-                    ty::BindByReference(mutbl) => {
-                        // If the binding is like
-                        //     ref x | ref const x | ref mut x
-                        // then `x` is assigned a value of type `&M T` where M is the mutability
-                        // and T is the expected type.
-                        let region_var = self.next_region_var(infer::PatternRegion(pat.span));
-                        let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
-                        let region_ty = tcx.mk_ref(region_var, mt);
-
-                        // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
-                        // required. However, we use equality, which is stronger. See (*) for
-                        // an explanation.
-                        self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
-                    }
-                    // Otherwise, the type of x is the expected type `T`.
-                    ty::BindByValue(_) => {
-                        // As above, `T <: typeof(x)` is required, but we
-                        // use equality, see (*) below.
-                        self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
-                    }
-                }
-
-                // If there are multiple arms, make sure they all agree on
-                // what the type of the binding `x` ought to be.
-                if var_id != pat.hir_id {
-                    let vt = self.local_ty(pat.span, var_id).decl_ty;
-                    self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
-                }
-
-                if let Some(ref p) = *sub {
-                    self.check_pat_walk(&p, expected, def_bm, discrim_span);
-                }
-
-                local_ty
+                let sub = sub.as_deref();
+                self.check_pat_ident(pat, ba, var_id, sub, expected, def_bm, discrim_span)
             }
             PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
                 self.check_pat_tuple_struct(
@@ -611,6 +566,67 @@ fn check_pat_range(
         Some(common_type)
     }
 
+    fn check_pat_ident(
+        &self,
+        pat: &hir::Pat,
+        ba: hir::BindingAnnotation,
+        var_id: hir::HirId,
+        sub: Option<&'tcx hir::Pat>,
+        expected: Ty<'tcx>,
+        def_bm: ty::BindingMode,
+        discrim_span: Option<Span>,
+    ) -> Ty<'tcx> {
+        // Determine the binding mode...
+        let bm = match ba {
+            hir::BindingAnnotation::Unannotated => def_bm,
+            _ => ty::BindingMode::convert(ba),
+        };
+        // ...and store it in a side table:
+        self.inh
+            .tables
+            .borrow_mut()
+            .pat_binding_modes_mut()
+            .insert(pat.hir_id, bm);
+
+        debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
+
+        let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
+        let eq_ty = match bm {
+            ty::BindByReference(mutbl) => {
+                // If the binding is like `ref x | ref const x | ref mut x`
+                // then `x` is assigned a value of type `&M T` where M is the
+                // mutability and T is the expected type.
+                let region_var = self.next_region_var(infer::PatternRegion(pat.span));
+                let mt = ty::TypeAndMut { ty: expected, mutbl };
+                let region_ty = self.tcx.mk_ref(region_var, mt);
+
+                // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
+                // is required. However, we use equality, which is stronger.
+                // See (*) for an explanation.
+                region_ty
+            }
+            // Otherwise, the type of x is the expected type `T`.
+            ty::BindByValue(_) => {
+                // As above, `T <: typeof(x)` is required, but we use equality, see (*) below.
+                expected
+            }
+        };
+        self.demand_eqtype_pat(pat.span, eq_ty, local_ty, discrim_span);
+
+        // If there are multiple arms, make sure they all agree on
+        // what the type of the binding `x` ought to be.
+        if var_id != pat.hir_id {
+            let vt = self.local_ty(pat.span, var_id).decl_ty;
+            self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
+        }
+
+        if let Some(p) = sub {
+            self.check_pat_walk(&p, expected, def_bm, discrim_span);
+        }
+
+        local_ty
+    }
+
     fn borrow_pat_suggestion(
         &self,
         err: &mut DiagnosticBuilder<'_>,